Salome HOME
Merge from V6_main (04/10/2012)
[modules/med.git] / src / MEDMEM / MEDMEM_GibiMeshDriver.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 <algorithm>
24 #include <queue>
25 #include <list>
26
27 #include "MEDMEM_GibiMeshDriver.hxx"
28
29 #ifdef HAS_XDR
30 // On windows, this file must be included first otherwise
31 // there is a conflict with the symbol GROUP when compiling the xdr support ...
32 #include <rpc/xdr.h>
33 #endif
34
35 #include "MEDMEM_DriversDef.hxx"
36
37 #include "MEDMEM_Family.hxx"
38 #include "MEDMEM_Field.hxx"
39 #include "MEDMEM_Group.hxx"
40 #include "MEDMEM_Coordinate.hxx"
41 #include "MEDMEM_Connectivity.hxx"
42 #include "MEDMEM_Mesh.hxx"
43 #include "MEDMEM_CellModel.hxx"
44 #include "MEDMEM_define.hxx"
45 #include "MEDMEM_DriverTools.hxx"
46
47 namespace MEDMEM
48 {
49 class FIELD_;
50 }
51
52 #include <stdio.h>
53 #include <fcntl.h>
54 #ifdef WIN32
55 #include <io.h>
56 #else
57 #include <unistd.h>
58 #endif
59
60 #include <float.h>
61
62 /////
63 using namespace std;
64 using namespace MED_EN;
65 using namespace MEDMEM;
66 /////
67
68 // read or not non-named fields
69 //#define GIBI_READ_ONLY_NAMED_FIELD
70
71 // to throw an exception when try to write a name longer than 8 or non-unique encounters
72 //#define THROW_ON_BAD_NAME
73
74 // to see full dump of RESULTATS STRUCTURE INTERMEDIAIRES
75 #ifdef _DEBUG_
76 // #undef MESSAGE_MED
77 // #define MESSAGE_MED(txt) std::cout << txt << endl;
78 // #undef INFOS_MED
79 // #define INFOS_MED(txt) std::cout << txt << endl;
80 #endif
81
82 // Every memory allocation made in the MedDriver members function are desallocated in the Mesh destructor
83
84 /////
85 //const size_t GIBI_MESH_DRIVER::nb_geometrie_gibi;
86
87 const medGeometryElement GIBI_MESH_DRIVER::geomGIBItoMED[nb_geometrie_gibi] =
88   {   /*1 */ MED_POINT1 ,/*2 */ MED_SEG2   ,/*3 */ MED_SEG3   ,/*4 */ MED_TRIA3  ,/*5 */ MED_NONE   ,
89       /*6 */ MED_TRIA6  ,/*7 */ MED_NONE   ,/*8 */ MED_QUAD4  ,/*9 */ MED_NONE   ,/*10*/ MED_QUAD8  ,
90       /*11*/ MED_NONE   ,/*12*/ MED_NONE   ,/*13*/ MED_NONE   ,/*14*/ MED_HEXA8  ,/*15*/ MED_HEXA20 ,
91       /*16*/ MED_PENTA6 ,/*17*/ MED_PENTA15,/*18*/ MED_NONE   ,/*19*/ MED_NONE   ,/*20*/ MED_NONE   ,
92       /*21*/ MED_NONE   ,/*22*/ MED_NONE   ,/*23*/ MED_TETRA4 ,/*24*/ MED_TETRA10,/*25*/ MED_PYRA5  ,
93       /*26*/ MED_PYRA13 ,/*27*/ MED_NONE   ,/*28*/ MED_NONE   ,/*29*/ MED_NONE   ,/*30*/ MED_NONE   ,
94       /*31*/ MED_NONE   ,/*32*/ MED_NONE   ,/*33*/ MED_NONE   ,/*34*/ MED_NONE   ,/*35*/ MED_NONE   ,
95       /*36*/ MED_NONE   ,/*37*/ MED_NONE   ,/*38*/ MED_NONE   ,/*39*/ MED_NONE   ,/*40*/ MED_NONE   ,
96       /*41*/ MED_NONE   ,/*42*/ MED_NONE   ,/*43*/ MED_NONE   ,/*44*/ MED_NONE   ,/*45*/ MED_NONE   ,
97       /*46*/ MED_NONE   ,/*47*/ MED_NONE   };
98
99 enum Readable_Piles
100   {
101     PILE_SOUS_MAILLAGE=1,
102     PILE_NODES_FIELD  =2,
103     PILE_TABLES       =10,
104     PILE_LREEL        =18,
105     PILE_LOGIQUES     =24,
106     PILE_FLOATS       =25,
107     PILE_INTEGERS     =26,
108     PILE_STRINGS      =27,
109     PILE_LMOTS        =29,
110     PILE_NOEUDS       =32,
111     PILE_COORDONNEES  =33,
112     PILE_MODL         =38,
113     PILE_FIELD        =39,
114     PILE_LAST_READABLE=39
115   };
116
117 //=======================================================================
118 //function : gibi2medGeom
119 //purpose  :
120 //=======================================================================
121
122 medGeometryElement GIBI_MESH_DRIVER::gibi2medGeom( size_t gibiTypeNb )
123 {
124   if ( gibiTypeNb < 1 || gibiTypeNb > 47 )
125     return MED_NONE;
126
127   return geomGIBItoMED[ gibiTypeNb - 1 ];
128 }
129
130 //=======================================================================
131 //function : med2gibiGeom
132 //purpose  :
133 //=======================================================================
134
135 int GIBI_MESH_DRIVER::med2gibiGeom( medGeometryElement medGeomType )
136 {
137   for ( int i = 0; i < nb_geometrie_gibi; i++ )
138     if ( geomGIBItoMED[ i ] == medGeomType )
139       return i + 1;
140
141   return -1;
142 }
143
144 //=======================================================================
145 //function : getGroupId
146 //purpose  :
147 //=======================================================================
148
149 static int getGroupId(const vector<int>& support_ids, _intermediateMED*  medi)
150 {
151   int group_id = 0;
152   vector<int>::const_iterator sb = support_ids.begin(), se = support_ids.end();
153   if (support_ids.size() == 1 || // one or equal support ids
154       *std::max_element( sb, se ) == *std::min_element( sb, se ))
155   {
156     group_id = support_ids[0] - 1;
157   }
158   else
159   {
160     // try to find an existing group with the same sub-groups
161     set<int> sup_set;
162     sup_set.insert( sb, se );
163
164     for ( group_id = 0; group_id < (int)medi->groupes.size(); ++group_id )
165     {
166       if (sup_set.size() == medi->groupes[ group_id ].groupes.size() &&
167           std::equal (sup_set.begin(), sup_set.end(),
168                       medi->groupes[ group_id ].groupes.begin()))
169         break;
170     }
171     if ( group_id == (int)medi->groupes.size() )
172     {
173       // no such a group, add a new one
174       medi->groupes.push_back( _groupe() );
175       _groupe& new_grp = medi->groupes.back();
176       new_grp.groupes.reserve( sup_set.size() );
177       for ( set<int>::iterator it = sup_set.begin(); it != sup_set.end(); it++ ) {
178         new_grp.groupes.push_back( *it );
179       }
180     }
181   }
182   return group_id;
183 }
184
185 //=======================================================================
186 //function : isNamedObject
187 //purpose  :
188 //=======================================================================
189
190 //#ifdef GIBI_READ_ONLY_NAMED_FIELD
191 static inline bool isNamedObject( int obj_index, const vector<int>& indices_objets_nommes )
192 {
193   return ( std::find( indices_objets_nommes.begin(), indices_objets_nommes.end(), obj_index)
194            != indices_objets_nommes.end() );
195 }
196 //#endif
197
198 //=======================================================================
199 //function : setFieldNames
200 //purpose  : set field names
201 //=======================================================================
202
203 static void setFieldNames(const vector< _fieldBase* >& fields,
204                           const vector<string>&        objets_nommes,
205                           const vector<int>&           indices_objets_nommes)
206 {
207   // set field names
208   unsigned i;
209   set<string> fnames;
210   for ( i = 0; i < indices_objets_nommes.size(); ++i ) {
211     int fieldIndex = indices_objets_nommes[ i ];
212     fnames.insert( objets_nommes[ i ]);
213     if ( fields[ fieldIndex - 1 ] )
214       fields[ fieldIndex - 1 ]->_name = objets_nommes[ i ];
215   }
216   int noNameIndex = 0;
217   for ( i = 0; i < fields.size(); ++i ) {
218     if ( !fields[ i ] ) {
219       if ( !isNamedObject( i+1, indices_objets_nommes ))
220         ++noNameIndex;
221     }
222     else if ( fields[ i ]->_name.empty() ) {
223       do {
224         fields[ i ]->_name = STRING("F_") << ++noNameIndex;
225       } while ( !fnames.insert( fields[ i ]->_name ).second );
226     }
227   }
228 }
229
230 //=======================================================================
231 //function : read
232 //purpose  :
233 //=======================================================================
234
235 #define GIBI_EQUAL(var_str, stat_str) \
236   (strncmp (var_str, stat_str, strlen(stat_str)) == 0)
237 #define DUMP_LINE_NB " on line " << _lineNb
238
239 bool GIBI_MESH_RDONLY_DRIVER::readFile (_intermediateMED* medi, bool readFields )
240 {
241   const char* LOC = "GIBI_MESH_RDONLY_DRIVER::readFile() : ";
242   BEGIN_OF_MED(LOC);
243
244   // LECTURE DES DONNEES DS FICHIER GIBI
245
246   Readable_Piles readable_Piles [] = {
247     PILE_SOUS_MAILLAGE,
248     PILE_NODES_FIELD,
249     PILE_TABLES,
250     PILE_LREEL,
251     PILE_LOGIQUES,
252     PILE_FLOATS,
253     PILE_INTEGERS,
254     PILE_STRINGS,
255     PILE_LMOTS,
256     PILE_NOEUDS,
257     PILE_COORDONNEES,
258     PILE_MODL,
259     PILE_FIELD,
260     PILE_LAST_READABLE
261   };
262   // other known piles:
263   // PILE NUMERO  26 - Integers
264   // PILE NUMERO  25 - Floats
265
266   char* ligne; // pour lire une ligne
267   const char* enregistrement_type=" ENREGISTREMENT DE TYPE";
268   vector<int> numero_noeuds; // tableau de travail (indices)
269   set<int> donePiles; // already read piles
270   unsigned space_dimension = 0;
271
272   // IMP 0020434: mapping GIBI names to MED names
273   list<nameGIBItoMED> listGIBItoMED_mail; // to be read from PILE_TABLES, from table "MED_MAIL"
274   list<nameGIBItoMED> listGIBItoMED_cham; // to be read from PILE_TABLES, from table "MED_CHAM"
275   list<nameGIBItoMED> listGIBItoMED_comp; // to be read from PILE_TABLES, from table "MED_COMP"
276   map<int,string> mapStrings; // to be read from PILE_STRINGS
277   vector<_fieldBase*> node_fields;
278   vector<_fieldBase*> cell_fields;
279
280 #ifdef HAS_XDR
281   if ( _is_xdr)
282     {
283       _curPos = 0;
284       _iRead = 0;
285       _nbToRead = 0;
286     }
287 #endif
288
289   while ( getNextLine(ligne, false)) // boucle externe de recherche de "ENREGISTREMENT DE TYPE"
290   {
291 #ifdef HAS_XDR
292     if ( !_is_xdr)
293 #endif
294       if ( !GIBI_EQUAL( ligne, enregistrement_type ))
295         continue; // "ENREGISTREMENT DE TYPE" non trouvé -> on lit la ligne suivante
296
297     // lecture du numéro d'enregistrement
298     int numero_enregistrement;
299 #ifdef HAS_XDR
300     if(_is_xdr)
301       numero_enregistrement = getInt();
302     else
303 #endif
304       numero_enregistrement = atoi( ligne + strlen(enregistrement_type) + 1 );
305
306     enum { ENREG_TYPE_2=2, ENREG_TYPE_4=4}; // Ã©numération des types d'enregistrement traités
307 #ifdef HAS_XDR
308     enum { ENREG_TYPE_5=5, ENREG_TYPE_7=7}; // (only for xdr)
309 #endif
310     int numero_pile, nb_objets_nommes, nb_objets, nb_indices;
311     vector<int> indices_objets_nommes;
312     vector<string> objets_nommes;
313
314     if (numero_enregistrement == ENREG_TYPE_4)
315     {
316 #ifdef HAS_XDR
317       if(_is_xdr)
318         {
319           getInt(); // skip NIVEAU
320           getInt(); // skip ERREUR
321           space_dimension = getInt();
322           getFloat(); // skip DENSITE
323         }
324       else
325         {
326 #endif
327           getNextLine(ligne);
328           const char* s = " NIVEAU  15 NIVEAU ERREUR   0 DIMENSION";
329           space_dimension = atoi( ligne + strlen( s ) + 1 );
330           if ( !GIBI_EQUAL( ligne, " NIVEAU" ) || space_dimension < 1 ) {
331             INFOS_MED( " Could not read file: syntax error in type 4 record" << DUMP_LINE_NB );
332             return false;
333           }
334 #ifdef HAS_XDR
335         }
336 #endif
337     }
338 #ifdef HAS_XDR
339     else if (numero_enregistrement == ENREG_TYPE_7)
340     {
341       if(_is_xdr)
342         {
343           getInt(); // skip NOMBRE INFO CASTEM2000
344           getInt(); // skip IFOUR
345           getInt(); // skip NIFOUR
346           getInt(); // skip IFOMOD
347           getInt(); // skip IECHO
348           getInt(); // skip IIMPI
349           getInt(); // skip IOSPI
350           getInt(); // skip ISOTYP
351           getInt(); // skip NSDPGE
352         }
353     }
354 #endif
355     else if (numero_enregistrement == ENREG_TYPE_2 )
356     {
357       if ( space_dimension == 0 ) {
358         INFOS_MED( "Missing ENREGISTREMENT DE TYPE   4" << DUMP_LINE_NB );
359         return false;
360       }
361       // FORMAT(' PILE NUMERO',I4,'NBRE OBJETS NOMMES',I8,'NBRE OBJETS',I8)
362       getNextLine(ligne);
363 #ifdef HAS_XDR
364       if(_is_xdr)
365         {
366           initIntReading(3);
367           numero_pile = getInt(); next();
368           nb_objets_nommes = getInt(); next();
369           nb_objets = getInt(); next();
370         }
371       else
372         {
373 #endif
374           const char *s1 = " PILE NUMERO", *s2 = "NBRE OBJETS NOMMES", *s3 = "NBRE OBJETS";
375           if ( ! GIBI_EQUAL( ligne, s1 ) ) {
376             INFOS_MED( " Could not read file: error in type 2 record. " << ligne << DUMP_LINE_NB );
377             return false;
378           }
379           ligne = ligne + strlen(s1);
380           numero_pile = atoi( ligne );
381           ligne = ligne + 4 + strlen(s2);
382           nb_objets_nommes = atoi( ligne );
383           ligne = ligne + 8 + strlen(s3);
384           nb_objets = atoi( ligne );
385 #ifdef HAS_XDR
386         }
387 #endif
388       if ( nb_objets_nommes<0 || nb_objets<0  ) {
389         INFOS_MED(" Could not read file: " << nb_objets << " " <<nb_objets_nommes << DUMP_LINE_NB );
390         return false;
391       }
392       if ( !donePiles.insert( numero_pile ).second ) // piles may repeat
393         continue;
394
395       if ( numero_pile > PILE_LAST_READABLE )
396         break; // stop file reading
397
398       // skip not readable piles
399       int i = -1;
400       while ( readable_Piles[ ++i ] != PILE_LAST_READABLE )
401         if ( readable_Piles[ i ] == numero_pile )
402           break;
403       if ( readable_Piles[ i ] != numero_pile )
404 #ifdef HAS_XDR
405         {
406           if(_is_xdr)
407             { 
408               cout << "XDR : NUMERO PILE " << numero_pile << " not implemented !!!" << endl ;
409               throw MEDEXCEPTION("XDR : NUMERO PILE not implemented !!!");
410             }
411 #endif
412           continue;
413 #ifdef HAS_XDR
414         }
415 #endif
416
417       // lecture des objets nommés et de leurs indices
418       objets_nommes.resize(nb_objets_nommes);
419       indices_objets_nommes.resize(nb_objets_nommes);
420       //indices_objets_nommes.resize(nb_objets);
421       for ( initNameReading( nb_objets_nommes ); more(); next() ) {
422         objets_nommes[ index() ] = getName();
423       }
424       for ( initIntReading( nb_objets_nommes ); more(); next() )
425       //for ( initIntReading( nb_objets ); more(); next() )
426         indices_objets_nommes[ index() ] = getInt();
427
428       // boucle interne : lecture de la pile
429
430       MESSAGE_MED(PREFIX_MED << "---- Traitement pile " << numero_pile);
431
432       // -----------------------------------
433       //                        MESH GROUPS
434       // -----------------------------------
435
436       if (numero_pile == PILE_SOUS_MAILLAGE ) // PILE NUMERO   1
437       {
438         map<int,int> strangeGroupType;
439         medi->groupes.reserve(nb_objets*2); // fields may add some groups
440         map< int , int > nbElemsByGeomType;
441
442         for (int objet=0; objet!=nb_objets; ++objet) // pour chaque groupe
443         {
444           initIntReading( 5 );
445           unsigned type_geom_castem = getInt(); next();
446           unsigned nb_sous_maillage = getInt(); next();
447           unsigned nb_reference     = getInt(); next();
448           unsigned nb_noeud         = getInt(); next();
449           unsigned nb_elements      = getInt();
450 #ifdef HAS_XDR
451           if(_is_xdr) next();
452 #endif
453
454           // le cas type_geom_castem=0 correspond aux maillages composites
455           if (type_geom_castem<0) {
456             INFOS_MED(" Error while reading file, bad geometric type:" <<
457                   type_geom_castem << DUMP_LINE_NB );
458             return false;
459           }
460
461           medi->groupes.push_back(_groupe());
462           _groupe & groupe = medi->groupes.back();
463
464           // Issue 0021311. Allocate places for names of referring groups
465           // that will be possibly filled after reading long names from
466           // PILE_TABLES and PILE_STRINGS
467           groupe.refNames.resize( nb_reference );
468
469           // si le groupe se compose de sous-maillages (ie groupe composite)
470           if (type_geom_castem==0 && nb_sous_maillage>0)
471           {
472             // lecture des indices des sous-maillages, stockage.
473             // les mailles correspondant a ces sous_maillages seront inserees a la fin du case
474             groupe.groupes.resize( nb_sous_maillage );
475             for ( initIntReading( nb_sous_maillage ); more(); next() ) {
476               groupe.groupes[ index() ] = getInt();
477             }
478             if ( readFields )
479               std::sort( groupe.groupes.begin(), groupe.groupes.end() );
480           }
481           // lecture des references (non utilisé pour MED)
482           for ( i = 0; i < (int)nb_reference; i += 10 ) {// FORMAT(10I8)
483             getNextLine(ligne);
484           }
485 #ifdef HAS_XDR
486           if(_is_xdr)
487             {
488               for (initIntReading(nb_reference); more(); next());
489             }
490 #endif
491           // lecture des couleurs (non utilisé pour MED)
492           for ( i = 0; i < (int)nb_elements; i += 10 ) {
493             getNextLine(ligne);
494           }
495 #ifdef HAS_XDR
496           if(_is_xdr)
497             {
498               for (initIntReading(nb_elements); more(); next());
499             }
500 #endif
501           // not a composit group
502           if (type_geom_castem>0 && nb_sous_maillage==0)
503           {
504             medGeometryElement medType = gibi2medGeom(type_geom_castem);
505
506             initIntReading( nb_elements * nb_noeud );
507             if ( medType == MED_NONE ) { // look for group end
508               while ( more() )
509                 next();
510               strangeGroupType.insert( make_pair( objet, type_geom_castem ));
511               continue;
512             }
513             if ( medType == MED_POINT1 )
514               medType = MED_NONE; // issue 21199
515             if ( nbElemsByGeomType.find( medType ) == nbElemsByGeomType.end())
516               nbElemsByGeomType[ medType ] = 0;
517             int & order = nbElemsByGeomType[ medType ];
518
519             pair<set<_maille>::iterator,bool> p;
520             pair<map<int,_noeud>::iterator,bool> p_no;
521             _noeud no;
522             no.coord.resize(space_dimension);
523             _maille ma( medType, nb_noeud );
524             ma.sommets.resize(nb_noeud);
525             groupe.mailles.resize( nb_elements );
526
527             // lecture pour chaque maille des sommets et insertions
528             for ( i = 0; i < int(nb_elements); ++i )
529             {
530               for (unsigned n = 0; n < nb_noeud; ++n, next() )
531               {
532                 if ( !more() ) {
533                   INFOS_MED( " Error while reading elem nodes ");
534                   return false;
535                 }
536                 no.number = getInt();
537                 p_no=medi->points.insert(make_pair(no.number, no));
538                 ma.sommets[n]=p_no.first;
539               }
540               ma.setOrdre( ++order );
541               // on stocke dans le groupe un iterateur sur la maille
542               groupe.mailles[i] = medi->insert(ma);
543             }
544           }
545         } // loop on groups
546
547         // set group names
548         for (i=0; i!=nb_objets_nommes; ++i) {
549           int grpID = indices_objets_nommes[i];
550           _groupe & grp = medi->groupes[ grpID-1 ];
551           if ( !grp.nom.empty() ) // a group has several names
552           { // create a group with subgroup grp and named grp.nom
553             medi->groupes.push_back(_groupe());
554             medi->groupes.back().groupes.push_back( grpID );
555             medi->groupes.back().nom = grp.nom;
556           }
557           grp.nom=objets_nommes[i];
558           map<int,int>::iterator it = strangeGroupType.find( grpID - 1 );
559           if ( it != strangeGroupType.end() ) {
560 #ifdef _DEBUG
561             cout << "Skip " << grp.nom << " of not supported CASTEM type: " << it->second << endl;
562 #endif
563             //INFOS_MED( "Skip " << grp.nom << " of not supported CASTEM type: " << it->second );
564           }
565         }
566
567       }// Fin case PILE_SOUS_MAILLAGE
568
569 #ifdef HAS_XDR
570
571       // ---------------------------------
572       // ---------------------------------
573       
574       else if ( numero_pile == PILE_LREEL ) // PILE NUMERO  18
575         {
576           if(_is_xdr)
577             {
578               for (int objet=0; objet!=nb_objets; ++objet) // pour chaque groupe
579                 {
580                   initIntReading(1);
581                   int nb_vals = getInt();
582                   next();
583                   initDoubleReading(nb_vals);
584                   for(i=0; i<nb_vals; i++) next();
585                 }
586             }
587         } // Fin case pile 18
588       
589       // ---------------------------------
590       // ---------------------------------
591       
592       else if ( numero_pile == PILE_LOGIQUES ) // PILE NUMERO  24
593         {
594           if(_is_xdr)
595             {
596               initIntReading(1);
597               int nb_vals = getInt();
598               next();
599               initIntReading(nb_vals);
600               for(i=0; i<nb_vals; i++) next();
601             }
602         } // Fin case pile 24
603       
604       // ---------------------------------
605       // ---------------------------------
606       
607       else if ( numero_pile == PILE_FLOATS ) // PILE NUMERO  25
608         {
609           if(_is_xdr)
610             {
611               initIntReading(1);
612               int nb_vals = getInt();
613               next();
614               initDoubleReading(nb_vals);
615               for(i=0; i<nb_vals; i++) next();
616             }
617         } // Fin case pile 25
618       
619       // ---------------------------------
620       // ---------------------------------
621       
622       else if ( numero_pile == PILE_INTEGERS ) // PILE NUMERO  26
623         {
624           if(_is_xdr)
625             {
626               initIntReading(1);
627               int nb_vals = getInt();
628               next();
629               initIntReading(nb_vals);
630               for(i=0; i<nb_vals; i++) next();
631             }
632         } // Fin case pile 26
633       
634       // ---------------------------------
635       // ---------------------------------
636       
637       else if ( numero_pile == PILE_LMOTS ) // PILE NUMERO  29
638         {
639           if(_is_xdr)
640             {
641               for (int objet=0; objet!=nb_objets; ++objet) // pour chaque groupe
642                 {
643                   initIntReading(2);
644                   int len = getInt();
645                   next();
646                   int nb_vals = getInt();
647                   next();
648                   int nb_char = len*nb_vals;
649                   int nb_char_tmp = 0;
650                   int fixed_length = 71;
651                   while (nb_char_tmp < nb_char)
652                     {
653                       int remain_len = nb_char - nb_char_tmp;
654                       int width;
655                       if ( remain_len > fixed_length )
656                         {
657                           width = fixed_length;
658                         }
659                       else
660                         {
661                           width = remain_len;
662                         }
663                       initNameReading(1, width);
664                       next();
665                       nb_char_tmp += width;
666                     }
667                 }
668             }
669         } // Fin case pile 29
670       
671       // ---------------------------------
672       // ---------------------------------
673       
674       else if ( numero_pile == PILE_MODL ) // PILE NUMERO  38
675         {
676           if(_is_xdr)
677             {
678               for (int objet=0; objet!=nb_objets; ++objet) // pour chaque groupe
679                 {
680                   // see wrmodl.eso
681                   initIntReading(10);
682                   int n1  = getInt() ; next();
683                   int nm2 = getInt() ; next();
684                   int nm3 = getInt() ; next();
685                   int nm4 = getInt() ; next();
686                   int nm5 = getInt() ; next();
687                   int n45 = getInt() ; next();
688                   /*int nm6 =*/ getInt() ; next();
689                   /*int nm7 =*/ getInt() ; next();
690                   next();
691                   next();
692                   int nm1 = n1 * n45;
693                   int nm9 = n1 * 16;
694                   for (initIntReading(nm1); more(); next());
695                   for (initIntReading(nm9); more(); next());
696                   for (initNameReading(nm5, 8); more(); next());
697                   for (initNameReading(nm2, 8); more(); next());
698                   for (initNameReading(nm3, 8); more(); next());
699                   for (initIntReading(nm4); more(); next());
700                 }
701             }
702         } // Fin case pile 38
703
704 #endif  // HAS_XDR
705       
706       // ---------------------------------
707       //                            NODES
708       // ---------------------------------
709
710       else if ( numero_pile == PILE_NOEUDS ) // PILE NUMERO  32
711       {
712         getNextLine( ligne );
713         std::vector<int> place_noeuds;
714 #ifdef HAS_XDR
715         if(_is_xdr) 
716           {
717             initIntReading(1);
718             nb_indices = getInt();
719             next();
720           }
721         else
722 #endif
723           nb_indices = atoi ( ligne );
724         if (nb_indices != nb_objets)
725         {
726           INFOS_MED("Erreur de lecture dans enregistrement de pile " <<
727                 PILE_NOEUDS << DUMP_LINE_NB );
728           return false;
729         }
730
731         place_noeuds.resize(nb_objets);
732         for ( initIntReading( nb_objets ); more(); next() )
733           place_noeuds[ index() ] = getInt();
734         int max=(* std::max_element(place_noeuds.begin(),place_noeuds.end()));
735
736         // numero_noeuds contient pour chacun des max noeuds qu'on va lire dans le case PILE_COORDONNEES
737         // son indice dans la connectivite du maillage. Cet indice correspond egalement a la cle du map
738         // medi->points ou l'on stocke les noeuds.
739         numero_noeuds.resize(max,-1);
740         for (unsigned i=0; i!=place_noeuds.size(); ++i)
741           numero_noeuds[place_noeuds[i]-1]=i+1;
742       }
743
744       // ---------------------------------------
745       //                            COORDINATES
746       // ---------------------------------------
747
748       else if ( numero_pile == PILE_COORDONNEES )// PILE NUMERO  33
749       {
750         getNextLine( ligne );
751         unsigned nb_reels;
752 #ifdef HAS_XDR
753         if(_is_xdr) 
754           {
755             initIntReading(1);
756             nb_reels = getInt();
757             next();
758           }
759         else
760 #endif
761           nb_reels = atoi( ligne );
762         // PROVISOIRE : certains fichier gibi n`ont
763         if (nb_reels < numero_noeuds.size()*(space_dimension)) {
764           INFOS_MED("Erreur de lecture dans enregistrement de pile " <<
765                 PILE_COORDONNEES << DUMP_LINE_NB );
766           return false;
767         }
768         initDoubleReading( nb_reels );
769         map< int, _noeud >::iterator pIt;
770         for (unsigned i=0; i!=numero_noeuds.size(); ++i)
771         {
772           // si le noeud est utilisé dans le maillage,
773           //on lit ses coordonnées et on les stocke dans la structure
774           if (( numero_noeuds[i] != -1 ) &&
775               (( pIt = medi->points.find(numero_noeuds[i])) != medi->points.end()))
776           {
777             for (unsigned j=0; j!=space_dimension; ++j, next())
778               pIt->second.coord[j] = getDouble();
779 #ifdef HAS_XDR
780             if(_is_xdr) getDouble(); // skip density
781 #endif
782             next(); // on ne conserve pas la densite
783           }
784           else // sinon, on passe au noeud suivant
785           {
786             for (unsigned j=0; j!=space_dimension+1; ++j)
787 #ifdef HAS_XDR
788               {
789                 if(_is_xdr) getDouble(); // skip ...
790 #endif
791                 next();
792 #ifdef HAS_XDR
793               }
794 #endif
795           }
796         }
797 #ifdef HAS_XDR
798         if(_is_xdr)
799           {
800             for(unsigned i=0; i!=nb_reels-numero_noeuds.size()*(space_dimension+1); ++i)
801               {
802                 next(); // skip ...
803               }
804           }
805 #endif
806       }
807
808       // ---------------------------------------
809       //                            NODE FIELDS
810       // ---------------------------------------
811
812       else if ( numero_pile == PILE_NODES_FIELD && readFields ) // PILE NUMERO   2
813       {
814         //vector< _fieldBase* > fields( nb_objets );
815         node_fields.resize(nb_objets, (_fieldBase*)0);
816         for (int objet=0; objet!=nb_objets; ++objet) // pour chaque field
817         {
818           bool ignoreField = false;
819 #ifdef GIBI_READ_ONLY_NAMED_FIELD
820           ignoreField = !isNamedObject( objet+1, indices_objets_nommes );
821           if ( ignoreField )
822             INFOS_MED("Skip non-named field " << objet+1 << DUMP_LINE_NB);
823 #endif
824
825           // EXAMPLE ( with no values )
826
827           // (1)       4       7       2       1
828           // (2)     -88       0       3     -89       0       1     -90       0       2     -91
829           // (2)       0       1
830           // (3) FX   FY   FZ   FZ   FX   FY   FLX
831           // (4)       0       0       0       0       0       0       0
832           // (5)           cree  par  muc pri
833           // (6)
834           // (7)       2
835
836           // (1): nb subcomponents, nb components(total), IFOUR, nb attributes
837           initIntReading( 4 );
838           int i_sub, nb_sub         = getInt(); next();
839           int i_comp, total_nb_comp = getInt(); next();
840           next(); // ignore IFOUR
841           int nb_attr = getInt();
842 #ifdef HAS_XDR
843           if(_is_xdr) next();
844 #endif
845           if ( nb_sub < 0 || total_nb_comp < 0 || nb_attr < 0 ) {
846             INFOS_MED("Error of field reading: wrong nb of components "
847                   << nb_sub << " " << total_nb_comp << DUMP_LINE_NB);
848             return false;
849           }
850           // (2) loop on subcomponents of a field, for each read
851           // (a) support, (b) number of values and (c) number of components
852           vector<int>     support_ids( nb_sub );
853           vector<int>     nb_values  ( nb_sub );
854           vector<int>     nb_comps   ( nb_sub );
855           int total_nb_values = 0;
856           initIntReading( nb_sub * 3 );
857           for ( i_sub = 0; i_sub < nb_sub; ++i_sub )
858           {
859             support_ids[ i_sub ] = -getInt(); next(); // (a) reference to support
860             if ( support_ids[ i_sub ] < 1 || support_ids[ i_sub ] > (int)medi->groupes.size() ) {
861               INFOS_MED("Error of field reading: wrong mesh reference "<<
862                     support_ids[ i_sub ] << DUMP_LINE_NB );
863               return false;
864             }
865             nb_values[ i_sub ] = getInt(); next();    // (b) nb points
866             total_nb_values += nb_values[ i_sub ];
867             if ( nb_values[ i_sub ] < 0 ) {
868               INFOS_MED(" Wrong nb of points: " << nb_values[ i_sub ]  << DUMP_LINE_NB );
869               return false;
870             }
871             nb_comps[ i_sub ] = getInt(); next();     // (c) nb of components in i_sub
872           }
873           // create a field if there are values
874           _field<double>* fdouble = 0;
875           if ( total_nb_values > 0 && !ignoreField )
876           {
877             fdouble = new _field<double>( MED_REEL64, nb_sub, total_nb_comp );
878             medi->fields.push_back( node_fields[ objet ] = fdouble );
879           }
880           // (3) component names
881           initNameReading( total_nb_comp, 4 );
882           for ( i_sub = 0; i_sub < nb_sub; ++i_sub )
883           {
884             // store support id and nb components of a sub
885             if ( fdouble )
886               fdouble->_sub[ i_sub ].setData( nb_comps[ i_sub ], support_ids[ i_sub ] );
887             for ( i_comp = 0; i_comp < nb_comps[ i_sub ]; ++i_comp, next() )
888             {
889               ASSERT_MED( more() );
890               // store component name
891               if ( fdouble )
892                 fdouble->_sub[ i_sub ].compName( i_comp ) = getName();
893             }
894           }
895           // (4) nb harmonics ( ignored )
896           for ( initIntReading( total_nb_comp ); more(); next() )
897             ;
898           // (5) TYPE ( ignored )
899           getNextLine( ligne );
900 #ifdef HAS_XDR
901           if(_is_xdr) for (initNameReading(1, 71); more(); next());
902 #endif
903           // (6) TITRE ( ignored )
904           getNextLine( ligne );
905 #ifdef HAS_XDR
906           if(_is_xdr) for (initNameReading(1, 71); more(); next());
907 #endif
908           // (7) attributes ( ignored )
909           for ( initIntReading( nb_attr ); more(); next() )
910             ;
911
912           for ( i_sub = 0; i_sub < nb_sub; ++i_sub )
913           {
914             // loop on components: read values
915             initDoubleReading( nb_values[ i_sub ] * nb_comps[ i_sub ] );
916             for ( i_comp = 0; i_comp < nb_comps[ i_sub ]; ++i_comp )
917             {
918               vector<double>* vals = 0;
919               if ( fdouble ) vals = & fdouble->addComponent( nb_values[ i_sub ] );
920               for ( int i = 0; more() && i < nb_values[ i_sub ]; next(), ++i ) {
921                 if ( vals ) (*vals)[ i ] = getDouble();
922               }
923             }
924           } // loop on subcomponents of a field
925
926           // set id of a group including all subs supports but only
927           // if all subs have the same components
928           if ( fdouble && fdouble->hasSameComponentsBySupport() )
929             fdouble->_group_id = getGroupId( support_ids, medi );
930
931         } // end loop on field objects
932
933         // set field names
934         setFieldNames( node_fields, objets_nommes, indices_objets_nommes );
935
936       }  // Fin numero_pile == PILE_NODES_FIELD
937
938       // -------------------------------------------------
939       //                                           FIELDS
940       // -------------------------------------------------
941
942       else if ( numero_pile == PILE_FIELD && readFields ) // PILE NUMERO  39
943       {
944         // REAL EXAMPLE
945
946         // (1)        1       2       6      16
947         // (2)                                                         CARACTERISTIQUES
948         // (3)      -15  317773       4       0       0       0      -2       0       3
949         // (4)             317581
950         // (5)  0
951         // (6)   317767  317761  317755  317815
952         // (7)  YOUN     NU       H        SIGY
953         // (8)  REAL*8            REAL*8            REAL*8            REAL*8
954         // (9)        1       1       0       0
955         // (10)  2.00000000000000E+05
956         // (11)       1       1       0       0
957         // (12)  3.30000000000000E-01
958         // (13)       1       1       0       0
959         // (14)  1.00000000000000E+04
960         // (15)       6     706       0       0
961         // (16)  1.00000000000000E+02  1.00000000000000E+02  1.00000000000000E+02
962         // (17)  1.00000000000000E+02  1.00000000000000E+02  1.00000000000000E+02
963         // (18)  ...
964
965         //vector< _fieldBase* > fields( nb_objets, (_fieldBase*)0 );
966         cell_fields.resize(nb_objets, (_fieldBase*)0);
967         for (int objet=0; objet!=nb_objets; ++objet) // pour chaque field
968         {
969           bool ignoreField = false;
970 #ifdef GIBI_READ_ONLY_NAMED_FIELD
971           ignoreField = !isNamedObject( objet+1, indices_objets_nommes );
972           if ( ignoreField )
973             INFOS_MED("Skip non-named field " << objet+1 << DUMP_LINE_NB);
974 #endif
975           initIntReading( 4 );
976           int i_sub, nb_sub = getInt(); // (1) <nb_sub> 2 6 <title length>
977           if ( nb_sub < 1 ) {
978             INFOS_MED("Error of field reading: wrong nb of subcomponents " <<
979                   nb_sub << DUMP_LINE_NB );
980             return false;
981           }
982           next(); next(); next(); // skip (1) <nb_sub> 2 6
983           int title_length = getInt(); // <title length>
984 #ifdef HAS_XDR
985           if(_is_xdr) next();
986 #endif
987           string description;
988           if ( title_length ) {
989 #ifdef HAS_XDR
990             if(_is_xdr)
991               {
992                 initNameReading(1, title_length);
993                 description = getName();
994                 next();
995               }
996             else
997               {
998 #endif
999                 getNextLine( ligne ); // (2) title
1000                 const int len = 72; // line length
1001                 // title is right justified
1002                 description = string(ligne + len - title_length, title_length);
1003               }
1004 #ifdef HAS_XDR
1005           }
1006 #endif
1007           // look for a line starting with '-' : <reference to support>
1008 #ifdef HAS_XDR
1009           if(_is_xdr)
1010             {
1011               initIntReading( nb_sub * 9 );
1012             }
1013           else
1014             {
1015 #endif
1016               do {
1017                 initIntReading( nb_sub * 9 );
1018               } while ( getInt() >= 0 );
1019 #ifdef HAS_XDR
1020             }
1021 #endif
1022           int total_nb_comp = 0;
1023           vector<int> support_ids( nb_sub ), nb_comp( nb_sub );
1024           for ( i_sub = 0; i_sub < nb_sub; ++i_sub )
1025           {                                           // (3)
1026             support_ids[ i_sub ] = -getInt(); next(); // <reference to support>
1027             next();                                   // ignore <address>
1028             nb_comp    [ i_sub ] =  getInt(); next(); // <nb of components in the sub>
1029             for ( i = 0; i < 6; ++i )                 // ignore 6 ints, in example 0 0 0 -2 0 3
1030               next();
1031             if ( support_ids[ i_sub ] < 1 || support_ids[ i_sub ] > (int)medi->groupes.size() ) {
1032               INFOS_MED("Error of field reading: wrong mesh reference "<<
1033                     support_ids[ i_sub ] << DUMP_LINE_NB );
1034               return false;
1035             }
1036             if ( nb_comp[ i_sub ] < 0 /*1*/ ) { // [SALOME platform 0019886]
1037               INFOS_MED("Error of field reading: wrong nb of components " <<
1038                     nb_comp[ i_sub ] << DUMP_LINE_NB );
1039               return false;
1040             }
1041             total_nb_comp += nb_comp[ i_sub ];
1042           }
1043           for ( initNameReading( nb_sub, 17 ); more(); next() )
1044             ; // (4) dummy strings
1045           for ( initNameReading( nb_sub ); more(); next() )
1046             ; // (5) dummy strings
1047
1048           // loop on subcomponents of a field, each of which refers to
1049           // a certain support and has its own number of components;
1050           // read component values
1051           _field<double>* fdouble = 0;
1052           _field<int>*    fint    = 0;
1053           _fieldBase *    fbase   = 0;
1054           for ( i_sub = 0; i_sub < nb_sub; ++ i_sub )
1055           {
1056             vector<string> comp_names( nb_comp[ i_sub ]), comp_type( nb_comp[ i_sub ]);
1057             for ( initIntReading( nb_comp[ i_sub ] ); more(); next() )
1058               ;  // (6) nb_comp addresses of MELVAL structure
1059
1060             // (7) component names
1061             for ( initNameReading( nb_comp[ i_sub ] ); more(); next() )
1062               comp_names[ index() ] = getName();
1063
1064             // (8) component type
1065             for ( initNameReading( nb_comp[ i_sub ], 17 ); more(); next() ) { // 17 is name width
1066               comp_type[ index() ] = getName();
1067               // component types must be the same
1068               if ( index() > 0 && comp_type[ index() ] != comp_type[ index() - 1] ) {
1069                 INFOS_MED( "Error of field reading: diff component types <"
1070                       << comp_type[ index() ] << "> != <" << comp_type[ index() - 1 ]
1071                        << ">" << DUMP_LINE_NB );
1072                 return false;
1073               }
1074             }
1075             // now type is known, create a field, one for all subs
1076             bool isReal = (nb_comp[i_sub] > 0) ? (comp_type[0] == "REAL*8") : true;
1077             if ( !ignoreField && !fbase && total_nb_comp ) {
1078               if ( !isReal ) {
1079                 fbase = fint = new _field<int>( MED_INT32, nb_sub, total_nb_comp );
1080                 INFOS_MED( "Warning: read NOT REAL field, type <" << comp_type[0] << ">"
1081                       << DUMP_LINE_NB);
1082               }
1083               else
1084                 fbase = fdouble = new _field<double>( MED_REEL64, nb_sub, total_nb_comp );
1085               medi->fields.push_back( cell_fields[ objet ] = fbase ); // medi->fields is a std::list
1086             }
1087             // store support id and nb components of a sub
1088             if ( fbase ) {
1089               fbase->_sub[ i_sub ].setData( nb_comp[ i_sub ], support_ids[ i_sub ]);
1090               fbase->_description = description;
1091             }
1092             // loop on components: read values
1093             for ( int i_comp = 0; i_comp < nb_comp[ i_sub ]; ++i_comp )
1094             {
1095               // (9) nb of values
1096 #ifdef HAS_XDR
1097               if(_is_xdr) initIntReading( 4 );
1098               else        initIntReading( 2 );
1099 #else
1100               initIntReading( 2 );
1101 #endif
1102               int nb_val_by_elem = getInt(); next();
1103               int nb_values      = getInt();
1104 #ifdef HAS_XDR
1105               if(_is_xdr) { next(); next(); next(); }
1106 #endif
1107               fbase->_sub[ i_sub ]._nb_gauss[ i_comp ] = nb_val_by_elem;
1108               // (10) values
1109               nb_values *= nb_val_by_elem;
1110               if ( fbase ) {
1111                 if ( isReal ) {
1112                   vector<double> & vals = fdouble->addComponent( nb_values );
1113                   for ( initDoubleReading( nb_values ); more(); next()) {
1114                     vals[ index() ] = getDouble();
1115                   }
1116                 }
1117                 else {
1118                   vector<int> & vals = fint->addComponent( nb_values );
1119                   for ( initIntReading( nb_values ); more(); next() ) {
1120                     vals[ index() ] = getInt();
1121                   }
1122                 }
1123                 // store component name
1124                 fbase->_sub[ i_sub ].compName( i_comp ) = comp_names[ i_comp ];
1125               }
1126               else {
1127                 for ( isReal ? initDoubleReading( nb_values ) : initIntReading( nb_values );
1128                       more();
1129                       next() ) ;
1130               }
1131             }
1132           } // loop on subcomponents of a field
1133
1134           // set id of a group including all sub supports but only
1135           // if all subs have the same nb of components
1136           if ( fbase && fbase->hasSameComponentsBySupport() )
1137             fbase->_group_id = getGroupId( support_ids, medi );
1138
1139         } // end loop on field objects
1140
1141         // set field names
1142         setFieldNames( cell_fields, objets_nommes, indices_objets_nommes );
1143
1144       } // numero_pile == PILE_FIELD && readFields
1145
1146       // ---------------------------------------
1147       //                            MED NAMES
1148       // ---------------------------------------
1149
1150       // IMP 0020434: mapping GIBI names to MED names
1151       else if (numero_pile == PILE_TABLES)
1152       {
1153         const char * table_med_mail = "MED_MAIL";
1154         const char * table_med_cham = "MED_CHAM";
1155         const char * table_med_comp = "MED_COMP";
1156
1157         int table_med_mail_id = -1;
1158         int table_med_cham_id = -1;
1159         int table_med_comp_id = -1;
1160
1161         for (int iname = 0; iname < nb_objets_nommes; iname++) {
1162           if (strcmp(objets_nommes[iname].c_str(), table_med_mail) == 0) {
1163             table_med_mail_id = indices_objets_nommes[iname];
1164           }
1165           else if (strcmp(objets_nommes[iname].c_str(), table_med_cham) == 0) {
1166             table_med_cham_id = indices_objets_nommes[iname];
1167           }
1168           else if (strcmp(objets_nommes[iname].c_str(), table_med_comp) == 0) {
1169             table_med_comp_id = indices_objets_nommes[iname];
1170           }
1171           else {
1172           }
1173         }
1174         //if (noms_med_id < 0) continue;
1175         if (table_med_mail_id < 0 && table_med_cham_id < 0 && table_med_comp_id < 0)
1176 #ifdef HAS_XDR
1177           if(!_is_xdr)
1178 #endif
1179             continue;
1180
1181         for (int itable = 1; itable <= nb_objets; itable++) {
1182           // read tables "MED_MAIL", "MED_CHAM" and "MED_COMP", that keeps correspondence
1183           // between GIBI names (8 symbols if any) and MED names (possibly longer)
1184           initIntReading(1);
1185           int nb_table_vals = getInt(); next();
1186           if (nb_table_vals < 0) {
1187             INFOS_MED("Erreur de lecture dans enregistrement de pile " <<
1188                       PILE_TABLES << DUMP_LINE_NB );
1189             return false;
1190           }
1191
1192           int name_i_med_pile;
1193           initIntReading(nb_table_vals);
1194           for (int i = 0; i < nb_table_vals/4; i++)
1195           {
1196             if (itable == table_med_mail_id ||
1197                 itable == table_med_cham_id ||
1198                 itable == table_med_comp_id)
1199             {
1200               nameGIBItoMED name_i;
1201               name_i_med_pile  = getInt(); next();
1202               name_i.med_id    = getInt(); next();
1203               name_i.gibi_pile = getInt(); next();
1204               name_i.gibi_id   = getInt(); next();
1205
1206               if (name_i_med_pile != PILE_STRINGS) {
1207                 // error: med(long) names are always kept in PILE_STRINGS
1208               }
1209
1210               if (itable == table_med_mail_id) {
1211                 if (name_i.gibi_pile != PILE_SOUS_MAILLAGE) {
1212                   // error: must be PILE_SOUS_MAILLAGE
1213                 }
1214                 listGIBItoMED_mail.push_back(name_i);
1215               }
1216               else if (itable == table_med_cham_id) {
1217                 if (name_i.gibi_pile != PILE_FIELD &&
1218                     name_i.gibi_pile != PILE_NODES_FIELD) {
1219                   // error: must be PILE_FIELD or PILE_NODES_FIELD
1220                 }
1221                 listGIBItoMED_cham.push_back(name_i);
1222               }
1223               else if (itable == table_med_comp_id) {
1224                 if (name_i.gibi_pile != PILE_STRINGS) {
1225                   // error: gibi(short) names of components are kept in PILE_STRINGS
1226                 }
1227                 listGIBItoMED_comp.push_back(name_i);
1228               }
1229               else {
1230               }
1231             }
1232             else
1233             {
1234               // pass table
1235               next(); next(); next(); next();
1236             }
1237           }
1238         } // for (int itable = 0; itable < nb_objets; itable++)
1239       } // numero_pile == PILE_TABLES
1240
1241       // ---------------------------------------
1242       //                            MED NAMES
1243       // ---------------------------------------
1244
1245       // IMP 0020434: mapping GIBI names to MED names
1246       else if (numero_pile == PILE_STRINGS)
1247       {
1248         initIntReading(2);
1249         int stringLen = getInt(); next();
1250         int nbSubStrings = getInt(); next();
1251         if (nbSubStrings != nb_objets) {
1252           // error
1253         }
1254         string aWholeString;
1255 #ifdef HAS_XDR
1256         if(_is_xdr)
1257           {
1258             const int fixedLength = 71;
1259             while ((int)aWholeString.length() < stringLen) {
1260               int remainLen = stringLen - aWholeString.length();
1261               int len;
1262               if ( remainLen > fixedLength )
1263                 {
1264                   len = fixedLength;
1265                 }
1266               else
1267                 {
1268                   len = remainLen;
1269                 }
1270               initNameReading(1, len);
1271               aWholeString += getName();
1272               next();
1273             }
1274           }
1275         else
1276           {
1277 #endif
1278             string aCurrLine;
1279             const int fixedLength = 71;
1280             while ((int)aWholeString.length() < stringLen) {
1281               getNextLine( ligne );
1282               int remainLen = stringLen - aWholeString.length();
1283               if ( remainLen > fixedLength )
1284                 {
1285                   aWholeString += ligne + 1;
1286                 }
1287               else
1288                 {
1289                   aWholeString += ligne + ( 72 - remainLen );
1290                 }
1291             }
1292 #ifdef HAS_XDR
1293           }
1294 #endif
1295         int prevOffset = 0;
1296         int currOffset = 0;
1297         initIntReading(nbSubStrings);
1298         for (int istr = 1; istr <= nbSubStrings; istr++, next()) {
1299           currOffset = getInt();
1300           // fill mapStrings
1301           mapStrings[istr] = aWholeString.substr(prevOffset, currOffset - prevOffset);
1302           prevOffset = currOffset;
1303         }
1304       }
1305
1306       else if ( numero_pile >= PILE_LAST_READABLE )
1307         break; // stop file reading
1308
1309     } // Fin case ENREG_TYPE_2
1310 #ifdef HAS_XDR
1311     else if (numero_enregistrement == ENREG_TYPE_5 )
1312     {
1313       if(_is_xdr)
1314         {
1315           break;
1316         }
1317     }
1318 #endif
1319 #ifdef HAS_XDR
1320     else
1321     {
1322       if(_is_xdr)
1323         {
1324           cout << "XDR : ENREGISTREMENT DE TYPE " << numero_enregistrement << " not implemented !!!" << endl;
1325           throw MEDEXCEPTION("XDR : ENREGISTREMENT DE TYPE not implemented !!!");
1326         }
1327     }
1328 #endif
1329   } //  fin de la boucle while de lecture externe
1330
1331   // IMP 0020434: mapping GIBI names to MED names
1332   // set med names to objects (mesh, fields, support, group or other)
1333   if (listGIBItoMED_mail.size() > 0) {
1334     set<int> treatedGroups;
1335     list<nameGIBItoMED>::iterator itGIBItoMED = listGIBItoMED_mail.begin();
1336     for (; itGIBItoMED != listGIBItoMED_mail.end(); itGIBItoMED++) {
1337       if ( (int)medi->groupes.size() < itGIBItoMED->gibi_id ) continue;
1338       _groupe & grp = medi->groupes[itGIBItoMED->gibi_id - 1];
1339       // if there are several names for grp then the 1st name is the name
1340       // of grp and the rest ones are names of groups referring grp (issue 0021311)
1341       const bool isRefName = !treatedGroups.insert( itGIBItoMED->gibi_id ).second;
1342       if ( !isRefName )
1343         grp.nom = mapStrings[ itGIBItoMED->med_id ];
1344       else
1345         for ( unsigned i = 0; i < grp.refNames.size(); ++i )
1346           if ( grp.refNames[i].empty() )
1347             grp.refNames[i] = mapStrings[ itGIBItoMED->med_id ];
1348     } // iterate on listGIBItoMED_mail
1349   }
1350   if (listGIBItoMED_cham.size() > 0) {
1351     list<nameGIBItoMED>::iterator itGIBItoMED = listGIBItoMED_cham.begin();
1352     for (; itGIBItoMED != listGIBItoMED_cham.end(); itGIBItoMED++) {
1353       if (itGIBItoMED->gibi_pile == PILE_FIELD) {
1354         cell_fields[itGIBItoMED->gibi_id - 1]->_name = mapStrings[itGIBItoMED->med_id];
1355       }
1356       else if (itGIBItoMED->gibi_pile == PILE_NODES_FIELD) {
1357         node_fields[itGIBItoMED->gibi_id - 1]->_name = mapStrings[itGIBItoMED->med_id];
1358       }
1359       else {
1360       }
1361     } // iterate on listGIBItoMED_cham
1362   }
1363   if (listGIBItoMED_comp.size() > 0) {
1364     list<nameGIBItoMED>::iterator itGIBItoMED = listGIBItoMED_comp.begin();
1365     for (; itGIBItoMED != listGIBItoMED_comp.end(); itGIBItoMED++)
1366       {
1367         string medName  = mapStrings[itGIBItoMED->med_id];
1368         string gibiName = mapStrings[itGIBItoMED->gibi_id];
1369
1370         bool name_found = false;
1371         for ( int isNodal = 0; isNodal < 2 && !name_found; ++isNodal )
1372           {
1373             vector<_fieldBase*> & fields = isNodal ? node_fields : cell_fields;
1374             for ( unsigned ifi = 0; ifi < fields.size() && !name_found; ifi++)
1375               {
1376                 if (medName.find( fields[ifi]->_name + "." ) == 0 ) {
1377                   std::vector<_fieldBase::_sub_data>& aSubDs = fields[ifi]->_sub;
1378                   int nbSub = aSubDs.size();
1379                   for (int isu = 0; isu < nbSub; isu++) {
1380                     for (int ico = 0; ico < aSubDs[isu].nbComponents(); ico++) {
1381                       if (aSubDs[isu].compName(ico) == gibiName) {
1382                         string medNameCompo = medName.substr( fields[ifi]->_name.size() + 1 );
1383                         fields[ifi]->_sub[isu].compName(ico) = medNameCompo;
1384                       }
1385                     }
1386                   }
1387                 }
1388               }
1389           }
1390       } // iterate on listGIBItoMED_comp
1391   }
1392
1393   // check if all needed piles present
1394   if ( donePiles.find( PILE_SOUS_MAILLAGE ) != donePiles.end() )
1395     {
1396       if (donePiles.find( PILE_NOEUDS ) == donePiles.end() ) {
1397         INFOS_MED( " Missing pile " << PILE_NOEUDS );
1398         return false;
1399       }
1400       if (donePiles.find( PILE_COORDONNEES ) == donePiles.end()) {
1401         INFOS_MED( " Missing pile " << PILE_COORDONNEES );
1402         return false;
1403       }
1404     }
1405
1406   END_OF_MED(LOC);
1407   return true;
1408 }
1409
1410 GIBI_MESH_DRIVER::GIBI_MESH_DRIVER():
1411        GENDRIVER(GIBI_DRIVER),
1412        _mesh(( GMESH *) NULL),
1413        _meshName("")
1414 {
1415   MESSAGE_MED("GIBI_MESH_DRIVER()");
1416 }
1417
1418 GIBI_MESH_DRIVER::GIBI_MESH_DRIVER(const string &         fileName,
1419                                    GMESH *                ptrMesh,
1420                                    MED_EN::med_mode_acces accessMode):
1421   GENDRIVER(fileName, accessMode, GIBI_DRIVER),
1422   _mesh(ptrMesh)
1423 {
1424   MESSAGE_MED( "GIBI_MESH_DRIVER(" << fileName <<","<<accessMode );
1425   // mesh name construction from fileName
1426   const string ext=".sauv"; // expected extension
1427   int pos=fileName.find(ext,0);
1428   int pos1=fileName.rfind('/');
1429   if ( pos < 0 || pos >= (int)fileName.size() ) pos = fileName.size();
1430 #ifdef WIN32
1431   if ( pos1 < 0 || pos1 >= (int)fileName.size() ) pos1 = fileName.rfind('\\');
1432 #endif
1433   if ( pos1 < 0 || pos1 >= (int)fileName.size() ) pos1 = -1;
1434   _meshName = string(fileName,pos1+1,pos-pos1-1); //get rid of directory & extension
1435   SCRUTE_MED(_meshName);
1436 }
1437
1438 GIBI_MESH_DRIVER::GIBI_MESH_DRIVER(const GIBI_MESH_DRIVER & driver):
1439   GENDRIVER(driver),
1440   _mesh(driver._mesh),
1441   _meshName(driver._meshName)
1442 {
1443   MESSAGE_MED("GIBI_MESH_DRIVER(const GIBI_MESH_DRIVER & driver)");
1444 }
1445
1446 GIBI_MESH_DRIVER::~GIBI_MESH_DRIVER()
1447 {
1448   MESSAGE_MED("~GIBI_MESH_DRIVER()");
1449 }
1450 void    GIBI_MESH_DRIVER::setMeshName(const string & meshName) { _meshName = meshName; }
1451 string  GIBI_MESH_DRIVER::getMeshName() const { return _meshName; }
1452
1453
1454 //---------------------------------- RDONLY PART ------------------------------------------
1455
1456 GIBI_MESH_RDONLY_DRIVER::GIBI_MESH_RDONLY_DRIVER():
1457   GIBI_MESH_DRIVER(),
1458   _File (-1),_start(0L),_ptr  (0L),_eptr (0L)
1459 {
1460 }
1461 GIBI_MESH_RDONLY_DRIVER::GIBI_MESH_RDONLY_DRIVER(const string & fileName,MESH * ptrMesh):
1462   GIBI_MESH_DRIVER(fileName,ptrMesh,RDONLY),
1463   _File (-1),_start(0L),_ptr  (0L),_eptr (0L)
1464 {
1465   MESSAGE_MED("GIBI_MESH_RDONLY_DRIVER::GIBI_MESH_RDONLY_DRIVER"
1466               "(const string & fileName, MESH * ptrMesh) has been created, "
1467               << fileName << ", " << RDONLY);
1468 }
1469 GIBI_MESH_RDONLY_DRIVER::GIBI_MESH_RDONLY_DRIVER(const GIBI_MESH_RDONLY_DRIVER & driver):
1470   GIBI_MESH_DRIVER(driver),
1471   _File (-1),_start(0L),_ptr  (0L),_eptr (0L)
1472 {
1473 }
1474
1475 GIBI_MESH_RDONLY_DRIVER::~GIBI_MESH_RDONLY_DRIVER()
1476 {
1477   const char* LOC = "~GIBI_MESH_RDONLY_DRIVER()";
1478   BEGIN_OF_MED(LOC);
1479   if (_File >= 0)
1480   {
1481 #ifdef HAS_XDR
1482     if(_is_xdr)
1483       {
1484         xdr_destroy((XDR*)_xdrs);
1485         free((XDR*)_xdrs);
1486         fclose(_xdrs_file);
1487       }
1488 #endif
1489     ::close (_File);
1490     if (_start != 0L)
1491       delete [] _start;
1492   }
1493   MESSAGE_MED("GIBI_MESH_RDONLY_DRIVER::~GIBI_MESH_RDONLY_DRIVER() has been destroyed");
1494 }
1495 GENDRIVER * GIBI_MESH_RDONLY_DRIVER::copy(void) const
1496 {
1497   return new GIBI_MESH_RDONLY_DRIVER(*this);
1498 }
1499
1500 //=======================================================================
1501 //function : open
1502 //purpose  :
1503 //=======================================================================
1504
1505 const int GIBI_MaxOutputLen   = 150;
1506 const int GIBI_BufferSize     = 16184; // for non-stream input
1507
1508 void GIBI_MESH_RDONLY_DRIVER::open()
1509   //     throw (MEDEXCEPTION)
1510 {
1511   if( _status == MED_OPENED )
1512     return;
1513
1514   const char * LOC = "GIBI_MESH_RDONLY_DRIVER::open()";
1515   BEGIN_OF_MED(LOC);
1516
1517 //   MED_EN::med_mode_acces aMode = getAccessMode();
1518 //   if ( aMode != MED_EN::MED_LECT && aMode != MED_EN::MED_REMP )
1519 //     throw MEDEXCEPTION(LOCALIZED(STRING(LOC) << " Bad file mode access ! " << aMode));
1520
1521 #ifdef WIN32
1522   _File = ::_open (_fileName.c_str(), _O_RDONLY|_O_BINARY);
1523 #else
1524   _File = ::open (_fileName.c_str(), O_RDONLY);
1525 #endif
1526   if (_File >= 0)
1527   {
1528     _start = new char [GIBI_BufferSize];
1529     _ptr   = _start;
1530     _eptr  = _start;
1531     _status = MED_OPENED;
1532     _lineNb = 0;
1533   }
1534   else
1535   {
1536     _status = MED_CLOSED;
1537     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<" Could not open file "<<_fileName
1538                                  << " fd: " << _File));
1539   }
1540
1541   // xdr
1542   
1543 #ifdef HAS_XDR
1544   _is_xdr = false;
1545   _xdrs_file = fdopen(_File, "r");
1546   _xdrs = (XDR *)malloc(sizeof(XDR));
1547   
1548   xdrstdio_create((XDR*)_xdrs, _xdrs_file, XDR_DECODE);
1549   
1550   const int maxsize = 10;
1551   char icha[maxsize+1];
1552   char *icha2=icha;
1553   bool_t xdr_test = xdr_string((XDR*)_xdrs, &icha2, maxsize);
1554   if(xdr_test)
1555     {
1556       icha[maxsize] = '\0';
1557       if(!strcmp(icha, "CASTEM XDR"))
1558         {
1559           _is_xdr = true;
1560         }
1561     }
1562   
1563   if(! _is_xdr)
1564     {
1565       xdr_destroy((XDR*)_xdrs);
1566       free((XDR*)_xdrs);
1567       fclose(_xdrs_file);
1568 #ifdef WIN32
1569       _File = ::_open (_fileName.c_str(), _O_RDONLY|_O_BINARY);
1570 #else
1571       ::close (_File); // ? needed ?
1572       _File = ::open (_fileName.c_str(), O_RDONLY);
1573 #endif
1574     }
1575 #endif
1576   
1577   END_OF_MED(LOC);
1578 }
1579
1580 //=======================================================================
1581 //function : close
1582 //purpose  :
1583 //=======================================================================
1584
1585 void GIBI_MESH_RDONLY_DRIVER::close()
1586 {
1587   const char* LOC = "GIBI_MESH_DRIVER::close() ";
1588   BEGIN_OF_MED(LOC);
1589   if ( _status == MED_OPENED) {
1590     if (_File >= 0) {
1591 #ifdef HAS_XDR
1592       if(_is_xdr)
1593         {
1594           xdr_destroy((XDR*)_xdrs);
1595           free((XDR*)_xdrs);
1596           fclose(_xdrs_file);
1597         }
1598 #endif
1599       ::close (_File);
1600       if (_start != 0L)
1601         delete [] _start;
1602       _File = -1;
1603     }
1604     _status = MED_CLOSED;
1605   }
1606   END_OF_MED(LOC);
1607 }
1608
1609 //=======================================================================
1610 //function : getLine
1611 //purpose  :
1612 //=======================================================================
1613
1614 bool GIBI_MESH_RDONLY_DRIVER::getLine(char* & aLine)
1615 {
1616 #ifdef HAS_XDR
1617   if (_is_xdr) return true;
1618 #endif
1619   bool aResult = true;
1620   // Check the state of the buffer;
1621   // if there is too little left, read the next portion of data
1622   int nBytesRest = _eptr - _ptr;
1623   if (nBytesRest < GIBI_MaxOutputLen)
1624   {
1625     if (nBytesRest > 0) {
1626       //memcpy (_start, _ptr, nBytesRest);
1627       char* tmpBuf = new char [nBytesRest];
1628       memcpy (tmpBuf, _ptr, nBytesRest);
1629       memcpy (_start, tmpBuf, nBytesRest);
1630       delete [] tmpBuf;
1631     } else
1632       nBytesRest = 0;
1633     _ptr = _start;
1634     const int nBytesRead = ::read (_File,
1635                                    &_start [nBytesRest],
1636                                    GIBI_BufferSize - nBytesRest);
1637     nBytesRest += nBytesRead;
1638     _eptr = &_start [nBytesRest];
1639   }
1640   // Check the buffer for the end-of-line
1641   char * ptr = _ptr;
1642   while (~0)
1643   {
1644     // Check for end-of-the-buffer, the ultimate criterion for termination
1645     if (ptr >= _eptr)
1646     {
1647       if (nBytesRest <= 0)
1648         aResult = false;
1649       else
1650         _eptr[-1] = '\0';
1651       break;
1652     }
1653     // seek the line-feed character
1654     if (ptr[0] == '\n')
1655     {
1656       if (ptr[-1] == '\r')
1657         ptr[-1] = '\0';
1658       ptr[0] = '\0';
1659       ++ptr;
1660       break;
1661     }
1662     ++ptr;
1663   }
1664   // Output the result
1665   aLine = _ptr;
1666   _ptr = ptr;
1667   _lineNb++;
1668
1669   return aResult;
1670 }
1671
1672 //=======================================================================
1673 //function : initNameReading
1674 //purpose  :
1675 //=======================================================================
1676
1677 void GIBI_MESH_RDONLY_DRIVER::initNameReading(int nbValues, int width)
1678 {
1679 #ifdef HAS_XDR
1680   if(_is_xdr)
1681     {
1682       _xdr_kind = _xdr_kind_char;
1683       if(nbValues)
1684         {
1685           unsigned int nels = nbValues*width;
1686           _xdr_cvals = (char*)malloc((nels+1)*sizeof(char));
1687           xdr_string((XDR*)_xdrs, &_xdr_cvals, nels);
1688           _xdr_cvals[nels] = '\0';
1689         }
1690     }
1691 #endif
1692   init( nbValues, 72 / ( width + 1 ), width, 1 );
1693 }
1694
1695 //=======================================================================
1696 //function : initIntReading
1697 //purpose  :
1698 //=======================================================================
1699
1700 void GIBI_MESH_RDONLY_DRIVER::initIntReading(int nbValues)
1701 {
1702 #ifdef HAS_XDR
1703   if(_is_xdr)
1704     {
1705       _xdr_kind = _xdr_kind_int;
1706       if(nbValues)
1707         {
1708           unsigned int nels = nbValues;
1709           unsigned int actual_nels;
1710           _xdr_ivals = (int*)malloc(nels*sizeof(int));
1711           xdr_array((XDR*)_xdrs, (char **)&_xdr_ivals, &actual_nels, nels, sizeof(int), (xdrproc_t)xdr_int);
1712         }
1713     }
1714 #endif
1715   init( nbValues, 10, 8 );
1716 }
1717
1718 //=======================================================================
1719 //function : initDoubleReading
1720 //purpose  :
1721 //=======================================================================
1722
1723 void GIBI_MESH_RDONLY_DRIVER::initDoubleReading(int nbValues)
1724 {
1725 #ifdef HAS_XDR
1726   if(_is_xdr)
1727     {
1728       _xdr_kind = _xdr_kind_double;
1729       if(nbValues)
1730         {
1731           unsigned int nels = nbValues;
1732           unsigned int actual_nels;
1733           _xdr_dvals = (double*)malloc(nels*sizeof(double));
1734           xdr_array((XDR*)_xdrs, (char **)&_xdr_dvals, &actual_nels, nels, sizeof(double), (xdrproc_t)xdr_double);
1735         }
1736     }
1737 #endif
1738   init( nbValues, 3, 22 );
1739 }
1740
1741 //=======================================================================
1742 //function : init
1743 //purpose  :
1744 //=======================================================================
1745
1746 void GIBI_MESH_RDONLY_DRIVER::init( int nbToRead, int nbPosInLine, int width, int shift )
1747 {
1748 #ifdef HAS_XDR
1749   if(_is_xdr)
1750     {
1751       if(_iRead < _nbToRead)
1752         {
1753           cout << "_iRead, _nbToRead : " << _iRead << " " << _nbToRead << endl;
1754           cout << "Unfinished iteration before new one !" << endl;
1755           throw MEDEXCEPTION("Unfinished iteration before new one !");
1756         }
1757     }
1758 #endif
1759   _nbToRead = nbToRead;
1760   _nbPosInLine = nbPosInLine;
1761   _width = width;
1762   _shift = shift;
1763   _iPos = _iRead = 0;
1764   if ( _nbToRead ) {
1765     getNextLine( _curPos );
1766     _curPos = _curPos + _shift;
1767   }
1768   else
1769     _curPos = 0;
1770 #ifdef HAS_XDR
1771   if(_is_xdr && (_xdr_kind == _xdr_kind_char))
1772     _curPos = _xdr_cvals;
1773 #endif
1774 }
1775
1776 //=======================================================================
1777 //function : more
1778 //purpose  :
1779 //=======================================================================
1780
1781 bool GIBI_MESH_RDONLY_DRIVER::more() const
1782 {
1783   bool result = false;
1784   if(_iRead < _nbToRead)
1785     {
1786       if(_curPos) result = true;
1787 #ifdef HAS_XDR
1788       if(_is_xdr) result = true;
1789 #endif
1790     }
1791   return result;
1792 }
1793
1794 //=======================================================================
1795 //function : next
1796 //purpose  : line getting
1797 //=======================================================================
1798
1799 void GIBI_MESH_RDONLY_DRIVER::next()
1800 {
1801   if ( !more() ) throw MEDEXCEPTION(LOCALIZED("!more()"));
1802   ++_iRead;
1803   ++_iPos;
1804   if ( _iRead < _nbToRead ) {
1805     if ( _iPos >= _nbPosInLine ) {
1806       getNextLine( _curPos );
1807       _curPos = _curPos + _shift;
1808       _iPos = 0;
1809     }
1810     else
1811       _curPos = _curPos + _width + _shift;
1812 #ifdef HAS_XDR
1813     if(_is_xdr && (_xdr_kind == _xdr_kind_char))
1814       {
1815         _curPos = _xdr_cvals + _iRead*_width;
1816       }
1817 #endif
1818   }
1819   else
1820     {
1821 #ifdef HAS_XDR
1822       if(_is_xdr)
1823         {
1824           if(_xdr_kind == _xdr_kind_char) free(_xdr_cvals);
1825           if(_xdr_kind == _xdr_kind_int) free(_xdr_ivals);
1826           if(_xdr_kind == _xdr_kind_double) free(_xdr_dvals);
1827           _xdr_kind = _xdr_kind_null;
1828         }
1829 #endif
1830       _curPos = 0;
1831     }
1832 }
1833
1834 //=======================================================================
1835 //function : getName
1836 //purpose  : names reading
1837 //=======================================================================
1838
1839 string GIBI_MESH_RDONLY_DRIVER::getName() const
1840 {
1841   int len = _width;
1842   while (( _curPos[len-1] == ' ' || _curPos[len-1] == 0) && len > 0 )
1843     len--;
1844   return string( _curPos, len );
1845 }
1846
1847 //=======================================================================
1848 //function : getInt
1849 //purpose  : int reading
1850 //=======================================================================
1851
1852 int GIBI_MESH_RDONLY_DRIVER::getInt() const
1853 {
1854 #ifdef HAS_XDR
1855   if(_is_xdr)
1856     {
1857       if(_iRead < _nbToRead)
1858         {
1859           return _xdr_ivals[_iRead];
1860         }
1861       else
1862         {
1863           int result;
1864           xdr_int((XDR*)_xdrs, &result);
1865           return result;
1866         }
1867     }
1868 #endif
1869   // fix for two glued ints (issue 0021009):
1870   // Line nb    |   File contents
1871   // ------------------------------------------------------------------------------------
1872   // 53619905   |       1       2       6       8
1873   // 53619906   |                                                                SCALAIRE
1874   // 53619907   |    -63312600499       1       0       0       0      -2       0       2
1875   //   where -63312600499 is actualy -633 and 12600499
1876   char hold=_curPos[_width];
1877   _curPos[_width] = '\0';
1878   int result = atoi(str());
1879   _curPos[_width] = hold;
1880   return result;
1881   //return atoi(str());
1882 }
1883
1884 //=======================================================================
1885 //function : getFloat
1886 //purpose  : float reading
1887 //=======================================================================
1888
1889 float GIBI_MESH_RDONLY_DRIVER::getFloat() const
1890 {
1891 #ifdef HAS_XDR
1892   if(_is_xdr)
1893     {
1894       float result;
1895       xdr_float((XDR*)_xdrs, &result);
1896       return result;
1897     }
1898 #endif
1899   return getDouble();
1900 }
1901
1902 //=======================================================================
1903 //function : getDouble
1904 //purpose  : double reading
1905 //=======================================================================
1906
1907 double GIBI_MESH_RDONLY_DRIVER::getDouble() const
1908 {
1909 #ifdef HAS_XDR
1910   if(_is_xdr)
1911     {
1912       if(_iRead < _nbToRead)
1913         {
1914           return _xdr_dvals[_iRead];
1915         }
1916       else
1917         {
1918           double result;
1919           xdr_double((XDR*)_xdrs, &result);
1920           return result;
1921         }
1922     }
1923 #endif
1924   
1925   //return atof(str());
1926
1927   std::string aStr (str());
1928
1929   // Correction 1: add missing 'E' specifier
1930   int aPosStart = aStr.find_first_not_of(" \t");
1931   if (aPosStart < (int)aStr.length()) {
1932     int aPosSign = aStr.find_first_of("+-", aPosStart + 1); // pass the leading symbol, as it can be a sign
1933     if (aPosSign < (int)aStr.length()) {
1934       if (aStr[aPosSign - 1] != 'e' && aStr[aPosSign - 1] != 'E')
1935         aStr.insert(aPosSign, "E", 1);
1936     }
1937   }
1938
1939   // Correction 2: set "C" numeric locale to read numbers
1940   // with dot decimal point separator, as it is in SAUVE files
1941   //char* aCurLocale = setlocale(LC_NUMERIC, 0);
1942   std::string aCurLocale = setlocale(LC_NUMERIC, 0);
1943   setlocale(LC_NUMERIC, "C");
1944   double ret = atof(aStr.data());
1945   //setlocale(LC_NUMERIC, aCurLocale);
1946   setlocale(LC_NUMERIC, aCurLocale.data());
1947
1948   return ret;
1949 }
1950
1951 //=======================================================================
1952 //function : read
1953 //purpose  :
1954 //=======================================================================
1955
1956 void GIBI_MESH_RDONLY_DRIVER::read(void) throw (MEDEXCEPTION)
1957 {
1958   const char * LOC = "_GIBI_RDONLY_DRIVER::read() : ";
1959   BEGIN_OF_MED(LOC);
1960
1961   if (_status!=MED_OPENED)
1962     throw MEDEXCEPTION(LOCALIZED(STRING(LOC) << "The _idt of file " << _fileName << " is : "
1963                                  <<  " (the file is not opened)." ));
1964   if ( ! _mesh->isEmpty() )
1965     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Mesh object not empty : can't fill it!"));
1966
1967   _intermediateMED medi;
1968   try {
1969     if ( readFile( &medi, false )) {
1970       // impression résultats
1971       MESSAGE_MED(LOC << "GIBI_MESH_RDONLY_DRIVER::read : RESULTATS STRUCTURE INTERMEDIAIRES : ");
1972       MESSAGE_MED(LOC <<  medi );
1973
1974       fillMesh( &medi );
1975       updateSupports(); // create families from groups etc.
1976     }
1977   }
1978   catch (MEDEXCEPTION &ex)
1979   {
1980     INFOS_MED( ex.what() );
1981   }
1982   END_OF_MED(LOC);
1983 }
1984
1985 //=======================================================================
1986 //function : getReverseVector
1987 //purpose  :
1988 //=======================================================================
1989
1990 static void getReverseVector (const medGeometryElement type,
1991                               vector<pair<int,int> > & swapVec )
1992 {
1993   const char* LOC = "void getReverseVector()";
1994   BEGIN_OF_MED(LOC);
1995   swapVec.clear();
1996
1997   switch ( type ) {
1998   case MED_TETRA4:
1999     swapVec.resize(1);
2000     swapVec[0] = make_pair( 1, 2 );
2001     break;
2002   case MED_PYRA5:
2003     swapVec.resize(1);
2004     swapVec[0] = make_pair( 1, 3 );
2005     break;
2006   case MED_PENTA6:
2007     swapVec.resize(2);
2008     swapVec[0] = make_pair( 1, 2 );
2009     swapVec[1] = make_pair( 4, 5 );
2010     break;
2011   case MED_HEXA8:
2012     swapVec.resize(2);
2013     swapVec[0] = make_pair( 1, 3 );
2014     swapVec[1] = make_pair( 5, 7 );
2015     break;
2016   case MED_TETRA10:
2017     swapVec.resize(3);
2018     swapVec[0] = make_pair( 1, 2 );
2019     swapVec[1] = make_pair( 4, 6 );
2020     swapVec[2] = make_pair( 8, 9 );
2021     break;
2022   case MED_PYRA13:
2023     swapVec.resize(4);
2024     swapVec[0] = make_pair( 1, 3 );
2025     swapVec[1] = make_pair( 5, 8 );
2026     swapVec[2] = make_pair( 6, 7 );
2027     swapVec[3] = make_pair( 10, 12 );
2028     break;
2029   case MED_PENTA15:
2030     swapVec.resize(4);
2031     swapVec[0] = make_pair( 1, 2 );
2032     swapVec[1] = make_pair( 4, 5 );
2033     swapVec[2] = make_pair( 6, 8 );
2034     swapVec[3] = make_pair( 9, 11 );
2035     break;
2036   case MED_HEXA20:
2037     swapVec.resize(7);
2038     swapVec[0] = make_pair( 1, 3 );
2039     swapVec[1] = make_pair( 5, 7 );
2040     swapVec[2] = make_pair( 8, 11 );
2041     swapVec[3] = make_pair( 9, 10 );
2042     swapVec[4] = make_pair( 12, 15 );
2043     swapVec[5] = make_pair( 13, 14 );
2044     swapVec[6] = make_pair( 17, 19 );
2045     break;
2046 //   case MED_SEG3: no need to reverse edges
2047 //     swapVec.resize(1);
2048 //     swapVec[0] = make_pair( 1, 2 );
2049 //     break;
2050   case MED_TRIA6:
2051     swapVec.resize(2);
2052     swapVec[0] = make_pair( 1, 2 );
2053     swapVec[1] = make_pair( 3, 5 );
2054     break;
2055   case MED_QUAD8:
2056     swapVec.resize(3);
2057     swapVec[0] = make_pair( 1, 3 );
2058     swapVec[1] = make_pair( 4, 7 );
2059     swapVec[2] = make_pair( 5, 6 );
2060     break;
2061   default:;
2062   }
2063   END_OF_MED(LOC);
2064 }
2065
2066 //=======================================================================
2067 //function : reverse
2068 //purpose  : inverse element orientation using vector of indices to swap
2069 //=======================================================================
2070
2071 static void reverse(const _maille & aMaille, const vector<pair<int,int> > & swapVec )
2072 {
2073   _maille* ma = (_maille*) & aMaille;
2074   for ( unsigned i = 0; i < swapVec.size(); ++i ) {
2075     std::swap( ma->sommets[ swapVec[i].first ],
2076                ma->sommets[ swapVec[i].second ]);
2077   }
2078   if ( swapVec.empty() )
2079     ma->reverse = true;
2080   else
2081     ma->reverse = false;
2082 }
2083
2084 //=======================================================================
2085 //function : getGibi2MedConnectivity
2086 //purpose  : return array of indices to transform GIBI connectivity to MED one
2087 //=======================================================================
2088
2089 static const int * getGibi2MedConnectivity( const medGeometryElement type )
2090 {
2091   static vector<const int*> conn;
2092   static int hexa20 [] = {0,6,4,2, 12,18,16,14, 7,5,3,1, 19,17,15,13, 8,11,10,9};
2093   static int penta15[] = {0,2,4, 9,11,13, 1,3,5, 10,12,14, 6,7,3};
2094   static int pyra13 [] = {0,2,4,6, 12, 1,3,5,7, 8,9,10,11};
2095   static int tetra10[] = {0,2,4, 9, 1,3,5, 6,7,8};
2096   static int quad8  [] = {0,2,4,6, 1,3,5,7};
2097   static int tria6  [] = {0,2,4, 1,3,5};
2098   static int seg3   [] = {0,2,1};
2099   if ( conn.empty() ) {
2100     conn.resize( MED_HEXA20 + 1, 0 );
2101     conn[ MED_HEXA20 ] = hexa20;
2102     conn[ MED_PENTA15] = penta15;
2103     conn[ MED_PYRA13 ] = pyra13;
2104     conn[ MED_TETRA10] = tetra10;
2105     conn[ MED_SEG3   ] = seg3;
2106     conn[ MED_TRIA6  ] = tria6;
2107     conn[ MED_QUAD8  ] = quad8;
2108   }
2109   return conn[ type ];
2110 }
2111
2112 //=======================================================================
2113 //function : fixConnectivity
2114 //purpose  : GIBI connectivity -> MED one
2115 //=======================================================================
2116
2117 static inline void fixConnectivity(const _maille & aMaille )
2118 {
2119   if ( const int * conn = getGibi2MedConnectivity( aMaille.geometricType )) {
2120     _maille* ma = (_maille*) & aMaille;
2121     //cout << "###### BEFORE fixConnectivity() " << *ma << endl;
2122     vector< _maille::TNoeud > newSommets( ma->sommets.size() );
2123     for ( unsigned i = 0; i < newSommets.size(); ++i )
2124       newSommets[ i ] = ma->sommets[ conn[ i ]];
2125     ma->sommets = newSommets;
2126     //cout << "###### AFTER fixConnectivity() " << *ma << endl;
2127   }
2128 }
2129
2130 //=======================================================================
2131 //function : orientElements
2132 //purpose  :
2133 //=======================================================================
2134
2135 static void orientElements( _intermediateMED& medi )
2136 {
2137   MESSAGE_MED("orientElements()");
2138
2139   set<_maille>::const_iterator elemIt, elemEnd;
2140
2141   int type = -100;
2142   vector< pair<int,int> > swapVec;
2143
2144   bool isQuadratic = false;
2145
2146   if ( medi.points.begin()->second.coord.size() == 2 ) { // space dimension
2147
2148     // fix connectivity of quadratic edges
2149     _maillageByDimIterator edgesIt( medi, /*dim=*/1);
2150     while ( const set<_maille > * edges = edgesIt.nextType() )
2151     {
2152       isQuadratic = getGibi2MedConnectivity( edgesIt.type() );
2153       if (isQuadratic )
2154       {
2155         elemIt = edges->begin(), elemEnd = edges->end();
2156         for ( ; elemIt != elemEnd; ++elemIt )
2157           fixConnectivity( *elemIt );
2158       }
2159     }
2160     // --------------------------
2161     // Orient 2D faces clockwise
2162     // --------------------------
2163
2164     _maillageByDimIterator faceMailIt( medi, /*dim=*/2 );
2165     while ( const set<_maille > * faces = faceMailIt.nextType() )
2166     {
2167       isQuadratic = getGibi2MedConnectivity( faceMailIt.type() );
2168       elemIt = faces->begin(), elemEnd = faces->end();
2169       for ( ; elemIt != elemEnd; elemIt++ )
2170       {
2171         // fix connectivity of quadratic faces
2172         if ( isQuadratic )
2173           fixConnectivity( *elemIt );
2174
2175         // look for index of the most left node
2176         int iLeft = 0, iNode, nbNodes = elemIt->sommets.size();
2177         if ( nbNodes > 4 ) // quadratic face
2178           nbNodes /= 2;
2179         double minX = elemIt->sommets[0]->second.coord[0];
2180         for ( iNode = 1; iNode < nbNodes; ++iNode )
2181         {
2182           if ( minX > elemIt->sommets[ iNode ]->second.coord[ 0 ]) {
2183             minX = elemIt->sommets[ iNode ]->second.coord[ 0 ];
2184             iLeft = iNode;
2185           }
2186         }
2187         // indeces of the nodes neighboring the most left one
2188         int iPrev = ( iLeft - 1 < 0 ) ? nbNodes - 1 : iLeft - 1;
2189         int iNext = ( iLeft + 1 == nbNodes ) ? 0 : iLeft + 1;
2190         // find components of prev-left and left-next vectors
2191         double xP = elemIt->sommets[ iPrev ]->second.coord[ 0 ];
2192         double yP = elemIt->sommets[ iPrev ]->second.coord[ 1 ];
2193         double xN = elemIt->sommets[ iNext ]->second.coord[ 0 ];
2194         double yN = elemIt->sommets[ iNext ]->second.coord[ 1 ];
2195         double xL = elemIt->sommets[ iLeft ]->second.coord[ 0 ];
2196         double yL = elemIt->sommets[ iLeft ]->second.coord[ 1 ];
2197         double xPL = xL - xP, yPL = yL - yP; // components of prev-left vector
2198         double xLN = xN - xL, yLN = yN - yL; // components of left-next vector
2199         // normalise y of the vectors
2200         double modPL = sqrt ( xPL * xPL + yPL * yPL );
2201         double modLN = sqrt ( xLN * xLN + yLN * yLN );
2202         if ( modLN > DBL_MIN && modPL > DBL_MIN )
2203         {
2204           yPL /= modPL;
2205           yLN /= modLN;
2206           // summury direction of neighboring links must be positive
2207           bool clockwise = ( yPL + yLN > 0 );
2208           if ( !clockwise ) {
2209             if ( elemIt->geometricType != type ) {
2210               type = elemIt->geometricType;
2211               getReverseVector( type, swapVec );
2212             }
2213             reverse( *elemIt, swapVec );
2214           }
2215         }
2216       }
2217     }
2218   }
2219   else {
2220
2221     // --------------------------------------
2222     // orient equally all connected 3D faces
2223     // --------------------------------------
2224     // connectivity of quadratic faces will be fixed by fixConnectivity()
2225     // in the next loop on elements
2226
2227     // fill map of links and their faces
2228     set<const _maille*> faces;
2229     map<const _maille*, _groupe*> fgm;
2230     map<_link, list<const _maille*> > linkFacesMap;
2231     map<_link, list<const _maille*> >::iterator lfIt, lfIt2;
2232
2233     medi.treatGroupes(); // erase groupes that wont be converted
2234     for (unsigned int i=0; i!=medi.groupes.size(); ++i)
2235     {
2236       _groupe& grp = medi.groupes[i];
2237       _groupe::TMailleIter maIt=grp.mailles.begin();
2238       if ( maIt==grp.mailles.end() || (*maIt)->dimensionWithPoly() != 2 )
2239         continue;
2240       for(; maIt!=grp.mailles.end(); ++maIt) {
2241         if ( faces.insert( &(**maIt )).second ) {
2242           for ( int j = 0; j < (int)(*maIt)->sommets.size(); ++j )
2243             linkFacesMap[ (*maIt)->link( j ) ].push_back( &(**maIt) );
2244           fgm.insert( make_pair( &(**maIt), &grp ));
2245         }
2246       }
2247     }
2248     // dump linkFacesMap
2249 //     for ( lfIt = linkFacesMap.begin(); lfIt!=linkFacesMap.end(); lfIt++) {
2250 //       cout<< "LINK: " << lfIt->first.first << "-" << lfIt->first.second << endl;
2251 //       list<const _maille*> & fList = lfIt->second;
2252 //       list<const _maille*>::iterator fIt = fList.begin();
2253 //       for ( ; fIt != fList.end(); fIt++ )
2254 //         cout << "\t" << **fIt << fgm[*fIt]->nom << endl;
2255 //     }
2256
2257     // Each oriented link must appear in one face only, else a face is reversed.
2258
2259     queue<const _maille*> faceQueue; // the queue contains well oriented faces
2260     // whose neighbors orientation is to be checked
2261
2262     bool manifold = true;
2263     while ( !linkFacesMap.empty() )
2264     {
2265       if ( faceQueue.empty() ) {
2266         ASSERT_MED( !linkFacesMap.begin()->second.empty() );
2267         faceQueue.push( linkFacesMap.begin()->second.front() );
2268       }
2269       while ( !faceQueue.empty() )
2270       {
2271         const _maille* face = faceQueue.front();
2272         faceQueue.pop();
2273
2274         // loop on links of <face>
2275         for ( int i = 0; i < (int)face->sommets.size(); ++i ) {
2276           _link link = face->link( i );
2277           // find the neighbor faces
2278           lfIt = linkFacesMap.find( link );
2279           int nbFaceByLink = 0;
2280           list< const _maille* > ml;
2281           if ( lfIt != linkFacesMap.end() )
2282           {
2283             list<const _maille*> & fList = lfIt->second;
2284             list<const _maille*>::iterator fIt = fList.begin();
2285             ASSERT_MED( fIt != fList.end() );
2286             for ( ; fIt != fList.end(); fIt++, nbFaceByLink++ ) {
2287               ml.push_back( *fIt );
2288               if ( *fIt != face ) // wrongly oriented neighbor face
2289               {
2290                 const _maille* badFace = *fIt;
2291                 // reverse and remove badFace from linkFacesMap
2292                 for ( int j = 0; j < (int)badFace->sommets.size(); ++j ) {
2293                   _link badlink = badFace->link( j );
2294                   if ( badlink == link ) continue;
2295                   lfIt2 = linkFacesMap.find( badlink );
2296                   if ( lfIt2 != linkFacesMap.end() ) {
2297                     list<const _maille*> & ff = lfIt2->second;
2298                     ff.erase( find( ff.begin(), ff.end(), badFace ));
2299                         if ( ff.empty() )
2300                           linkFacesMap.erase( lfIt2 );
2301                   }
2302                 }
2303                 badFace->reverse = true; // reverse
2304                 //INFOS_MED( "REVERSE " << *badFace );
2305                 faceQueue.push( badFace );
2306               }
2307             }
2308             linkFacesMap.erase( lfIt );
2309           }
2310           // add good neighbors to the queue
2311           _link revLink( link.second, link.first );
2312           lfIt = linkFacesMap.find( revLink );
2313           if ( lfIt != linkFacesMap.end() )
2314           {
2315             list<const _maille*> & fList = lfIt->second;
2316             list<const _maille*>::iterator fIt = fList.begin();
2317             for ( ; fIt != fList.end(); fIt++, nbFaceByLink++ ) {
2318               ml.push_back( *fIt );
2319               if ( *fIt != face )
2320                 faceQueue.push( *fIt );
2321             }
2322             linkFacesMap.erase( lfIt );
2323           }
2324           if ( nbFaceByLink > 2 ) {
2325             if ( manifold ) {
2326               list<const _maille*>::iterator i = ml.begin();
2327               INFOS_MED(nbFaceByLink << " faces by 1 link:");
2328               for( ; i!= ml.end(); i++ ) {
2329                 INFOS_MED("in object " << fgm[ *i ]->nom);
2330                 INFOS_MED( **i );
2331               }
2332             }
2333             manifold = false;
2334           }
2335         } // loop on links of the being checked face
2336       } // loop on the face queue
2337     } // while ( !linkFacesMap.empty() )
2338
2339     if ( !manifold )
2340       INFOS_MED(" -> Non manifold mesh, faces orientation may be incorrect");
2341
2342
2343     // ---------------------------------------------------
2344     // fix connectivity of quadratic elements
2345     // ---------------------------------------------------
2346
2347     for ( int dim = 1; dim <= 3; ++dim )
2348     {
2349       _maillageByDimIterator mailIt( medi, dim );
2350       while ( const set<_maille > * elems = mailIt.nextType() )
2351       {
2352         isQuadratic = getGibi2MedConnectivity( mailIt.type() );
2353         elemIt = elems->begin(), elemEnd = elems->end();
2354         for ( ; elemIt != elemEnd; elemIt++ )
2355         {
2356           // GIBI connectivity -> MED one
2357           if ( isQuadratic )
2358             fixConnectivity( *elemIt );
2359
2360           // reverse quadratic faces
2361           if ( elemIt->reverse ) {
2362             if ( elemIt->geometricType != type ) {
2363               type = elemIt->geometricType;
2364               getReverseVector( type, swapVec );
2365             }
2366             reverse ( *elemIt, swapVec );
2367           }
2368         }
2369       }
2370     }
2371
2372     // ---------------------------------------------------
2373     // Orient volumes according to MED conventions:
2374     // normal of a bottom (first) face should be downward
2375     // ---------------------------------------------------
2376
2377     _maillageByDimIterator mailIt( medi, 3 );
2378     while ( const set<_maille > * elems = mailIt.nextType() )
2379     {
2380       elemIt = elems->begin(), elemEnd = elems->end();
2381       int nbBottomNodes = 0;
2382       switch ( elemIt->geometricType ) {
2383       case MED_TETRA4:
2384       case MED_TETRA10:
2385       case MED_PENTA6:
2386       case MED_PENTA15:
2387         nbBottomNodes = 3; break;
2388       case MED_PYRA5:
2389       case MED_PYRA13:
2390       case MED_HEXA8:
2391       case MED_HEXA20:
2392         nbBottomNodes = 4; break;
2393       default: continue;
2394       }
2395       getReverseVector( elemIt->geometricType, swapVec );
2396
2397       for ( ; elemIt != elemEnd; elemIt++ )
2398       {
2399         // find a normal to the bottom face
2400         const _noeud* n[4] = {
2401           &elemIt->sommets[0]->second, // 3 bottom nodes
2402           &elemIt->sommets[1]->second,
2403           &elemIt->sommets[2]->second,
2404           &elemIt->sommets[nbBottomNodes]->second };// a top node
2405         double vec01 [3] = { // vector n[0]-n[1]
2406           n[1]->coord[0] - n[0]->coord[0],
2407           n[1]->coord[1] - n[0]->coord[1],
2408           n[1]->coord[2] - n[0]->coord[2], };
2409         double vec02 [3] = { // vector n[0]-n[2]
2410           n[2]->coord[0] - n[0]->coord[0],
2411           n[2]->coord[1] - n[0]->coord[1],
2412           n[2]->coord[2] - n[0]->coord[2] };
2413         double normal [3] = { // vec01 ^ vec02
2414           vec01[1] * vec02[2] - vec01[2] * vec02[1],
2415           vec01[2] * vec02[0] - vec01[0] * vec02[2],
2416           vec01[0] * vec02[1] - vec01[1] * vec02[0] };
2417         // check if the 102 angle is convex
2418         if ( nbBottomNodes > 3 ) {
2419           const _noeud* n3 = &elemIt->sommets[nbBottomNodes-1]->second;// last bottom node
2420           double vec03 [3] = { // vector n[0]-n3
2421             n3->coord[0] - n[0]->coord[0],
2422             n3->coord[1] - n[0]->coord[1],
2423             n3->coord[2] - n[0]->coord[2], };
2424           if ( fabs( normal[0]+normal[1]+normal[2] ) <= DBL_MIN ) { // vec01 || vec02
2425             normal[0] = vec01[1] * vec03[2] - vec01[2] * vec03[1]; // vec01 ^ vec03
2426             normal[1] = vec01[2] * vec03[0] - vec01[0] * vec03[2];
2427             normal[2] = vec01[0] * vec03[1] - vec01[1] * vec03[0];
2428           }
2429           else {
2430             double vec [3] = { // normal ^ vec01
2431               normal[1] * vec01[2] - normal[2] * vec01[1],
2432               normal[2] * vec01[0] - normal[0] * vec01[2],
2433               normal[0] * vec01[1] - normal[1] * vec01[0] };
2434             double dot2 = vec[0]*vec03[0] + vec[1]*vec03[1] + vec[2]*vec03[2]; // vec*vec03
2435             if ( dot2 < 0 ) { // concave -> reverse normal
2436               normal[0] *= -1;
2437               normal[1] *= -1;
2438               normal[2] *= -1;
2439             }
2440           }
2441         }
2442         // direction from top to bottom
2443         double tbDir[3];
2444         tbDir[0] = n[0]->coord[0] - n[3]->coord[0];
2445         tbDir[1] = n[0]->coord[1] - n[3]->coord[1];
2446         tbDir[2] = n[0]->coord[2] - n[3]->coord[2];
2447         // compare 2 directions: normal and top-bottom
2448         double dot = normal[0]*tbDir[0] + normal[1]*tbDir[1] + normal[2]*tbDir[2];
2449         if ( dot < 0. ) // need reverse
2450         {
2451           reverse( *elemIt, swapVec );
2452         }
2453       } // loop on volumes of one geometry
2454     } // loop on 3D geometry types
2455
2456   } // space dimension == 3
2457 }
2458
2459 //=======================================================================
2460 //function : fillMesh
2461 //purpose  : load data from medi to mesh
2462 //=======================================================================
2463
2464 void GIBI_MESH_RDONLY_DRIVER::fillMesh(_intermediateMED* _ptrMedi)
2465 {
2466   const char* LOC = "GIBI_MESH_RDONLY_DRIVER::fillMesh(_intermediateMED* _ptrMedi) : ";
2467   BEGIN_OF_MED(LOC);
2468
2469   MESH* mesh = (MESH*)_mesh;
2470   mesh->_name = _meshName;
2471
2472   if (_ptrMedi)
2473   {
2474     if (!_maillageByDimIterator(*_ptrMedi).nextType() ||
2475         _ptrMedi->groupes.empty() ||
2476         _ptrMedi->points.empty()) {
2477       INFOS_MED(" Error while reading file: the data read are not completed " );
2478       return;
2479     }
2480     // fix element orientation
2481     orientElements( *_ptrMedi );
2482
2483     mesh->_spaceDimension = _ptrMedi->points.begin()->second.coord.size();
2484     mesh->_numberOfNodes  = _ptrMedi->points.size();
2485     mesh->_coordinate     = _ptrMedi->getCoordinate();
2486
2487     //Construction des groupes
2488     _ptrMedi->getGroups(mesh->_groupCell,
2489                         mesh->_groupFace,
2490                         mesh->_groupEdge,
2491                         mesh->_groupNode, mesh);
2492
2493     mesh->_connectivity = _ptrMedi->getConnectivity();
2494   }
2495   END_OF_MED(LOC);
2496 }
2497
2498 //================================================================================
2499 /*!
2500  * \brief Create families from groups etc.
2501  */
2502 //================================================================================
2503
2504 void GIBI_MESH_RDONLY_DRIVER::updateSupports()
2505 {
2506   _mesh->createFamilies();
2507
2508   // add attributes to families
2509   set<string> famNames;
2510   for (medEntityMesh entity=MED_CELL; entity<MED_ALL_ENTITIES; ++entity)
2511   {
2512     int i, nb = _mesh->getNumberOfFamilies(entity);
2513     for ( i = 1; i <= nb; ++i ) {
2514       FAMILY* f = const_cast<FAMILY*>( _mesh->getFamily( entity, i ));
2515       f->setNumberOfAttributes( 1 );
2516       int* attIDs = new int[1];
2517       attIDs[0] = 1;
2518       f->setAttributesIdentifiers( attIDs );
2519       int* attVals = new int[1];
2520       attVals[0] = 1;
2521       f->setAttributesValues( attVals );
2522       string* attDescr = new string[1];
2523       attDescr[0] = "med_family";
2524       f->setAttributesDescriptions( attDescr );
2525       delete [] attDescr;
2526       // limit a name length
2527       if ( f->getName().length() > 31 ) {
2528         ostringstream name;
2529         name << "FAM" << f->getIdentifier();
2530         f->setName( name.str());
2531       }
2532       // check if family is on the whole mesh entity
2533       if (_mesh->getNumberOfElements( entity, MED_ALL_ELEMENTS ) ==
2534           f->getNumberOfElements( MED_ALL_ELEMENTS ))
2535         f->setAll( true );
2536     }
2537     // setAll() for groups
2538     nb = _mesh->getNumberOfGroups(entity);
2539     for ( i = 1; i <= nb; ++i ) {
2540       GROUP * g = const_cast<GROUP*>( _mesh->getGroup( entity, i ));
2541       if (_mesh->getNumberOfElements( entity, MED_ALL_ELEMENTS ) ==
2542           g->getNumberOfElements( MED_ALL_ELEMENTS ))
2543         g->setAll( true );
2544     }
2545   }
2546 }
2547
2548 void GIBI_MESH_RDONLY_DRIVER::write( void ) const
2549   throw (MEDEXCEPTION)
2550 {
2551   throw MEDEXCEPTION("GIBI_MESH_RDONLY_DRIVER::write : Can't write with a RDONLY driver !");
2552 }
2553
2554
2555 /*--------------------- WRONLY PART -------------------------------*/
2556
2557 GIBI_MESH_WRONLY_DRIVER::GIBI_MESH_WRONLY_DRIVER():GIBI_MESH_DRIVER()
2558 {
2559 }
2560 GIBI_MESH_WRONLY_DRIVER::GIBI_MESH_WRONLY_DRIVER(const string & fileName,
2561                                                  GMESH *        ptrMesh):
2562   GIBI_MESH_DRIVER(fileName,ptrMesh,WRONLY)
2563 {
2564   MESSAGE_MED("GIBI_MESH_WRONLY_DRIVER::GIBI_MESH_WRONLY_DRIVER(const string & fileName, MESH * ptrMesh) has been created");
2565 }
2566 GIBI_MESH_WRONLY_DRIVER::GIBI_MESH_WRONLY_DRIVER(const GIBI_MESH_WRONLY_DRIVER & driver):
2567   GIBI_MESH_DRIVER(driver)
2568 {
2569 }
2570 GIBI_MESH_WRONLY_DRIVER::~GIBI_MESH_WRONLY_DRIVER()
2571 {
2572   //MESSAGE_MED("GIBI_MESH_WRONLY_DRIVER::GIBI_MESH_WRONLY_DRIVER(const string & fileName, MESH * ptrMesh) has been destroyed");
2573 }
2574 GENDRIVER * GIBI_MESH_WRONLY_DRIVER::copy(void) const
2575 {
2576   return new GIBI_MESH_WRONLY_DRIVER(*this);
2577 }
2578 void GIBI_MESH_WRONLY_DRIVER::read (void)
2579   throw (MEDEXCEPTION)
2580 {
2581   throw MEDEXCEPTION("GIBI_MESH_WRONLY_DRIVER::read : Can't read with a WRONLY driver !");
2582 }
2583
2584 //=======================================================================
2585 //function : open
2586 //purpose  :
2587 //=======================================================================
2588
2589 void GIBI_MESH_WRONLY_DRIVER::open()
2590   //     throw (MEDEXCEPTION)
2591 {
2592   if( _status == MED_OPENED )
2593     return;
2594
2595   const char * LOC = "GIBI_MESH_DRIVER::open()";
2596   BEGIN_OF_MED(LOC);
2597
2598   MED_EN::med_mode_acces aMode = getAccessMode();
2599   switch (aMode) {
2600   case MED_EN::RDWR:
2601   case MED_EN::WRONLY: // should never append !!
2602     _gibi.open(_fileName.c_str(), ios::out);
2603     break;
2604   default:
2605     throw MEDEXCEPTION(LOCALIZED(STRING(LOC) << "Bad file mode access ! " << aMode));
2606   }
2607   //change for windows compilation
2608   if ( !_gibi ||
2609 #ifdef WIN32
2610       !_gibi.is_open()
2611 #else
2612       !_gibi.rdbuf()->is_open()
2613 #endif
2614       )
2615   {
2616     _status = MED_CLOSED;
2617     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<" Could not open file "<<_fileName));
2618   }
2619   else
2620   {
2621     _status = MED_OPENED;
2622   }
2623   END_OF_MED(LOC);
2624 }
2625
2626 //=======================================================================
2627 //function : close
2628 //purpose  :
2629 //=======================================================================
2630
2631 void GIBI_MESH_WRONLY_DRIVER::close()
2632   //  throw (MEDEXCEPTION)
2633 {
2634   const char* LOC = "GIBI_MESH_DRIVER::close() ";
2635   BEGIN_OF_MED(LOC);
2636     if ( _status == MED_OPENED)
2637     {
2638         _gibi.close();
2639         _status = MED_CLOSED;
2640     }
2641   END_OF_MED(LOC);
2642 }
2643
2644 //=======================================================================
2645 //function : write
2646 //purpose  :
2647 //=======================================================================
2648
2649 void GIBI_MESH_WRONLY_DRIVER::write(void) const
2650   throw (MEDEXCEPTION)
2651 {
2652   const char* LOC = "void GIBI_MESH_WRONLY_DRIVER::write(void) const : ";
2653   BEGIN_OF_MED(LOC);
2654
2655   // we are going to modify the _gibi field
2656   GIBI_MESH_WRONLY_DRIVER * me = const_cast<GIBI_MESH_WRONLY_DRIVER *>(this);
2657 //  try {
2658     // IMP 0020434: mapping GIBI names to MED names
2659     list<nameGIBItoMED> listGIBItoMED_mail;
2660     list<nameGIBItoMED> listGIBItoMED_cham;
2661     list<nameGIBItoMED> listGIBItoMED_comp;
2662     me->writeSupportsAndMesh(listGIBItoMED_mail);
2663     me->writeMEDNames(listGIBItoMED_mail, listGIBItoMED_cham, listGIBItoMED_comp);
2664     me->writeLastRecord();
2665 //   }
2666 //   catch (MEDEXCEPTION &ex)
2667 //   {
2668 //     INFOS_MED( ex.what() );
2669 //   }
2670
2671   END_OF_MED(LOC);
2672 }
2673
2674 //=======================================================================
2675 //function : getName
2676 //purpose  : return cleaned up support name
2677 //=======================================================================
2678
2679 static string cleanName( const string& theName )
2680 {
2681   string name = theName;
2682   if ( !name.empty() ) {
2683     /*
2684     // find a name string end
2685     int i, len = name.length();
2686     for ( i = 0; i < len; ++i ) {
2687       if ( name[i] == 0 )
2688         break;
2689     }
2690     // cut off trailing white spaces
2691     while ( i > 0 && name[i-1] == ' ' )
2692       i--;
2693     if ( i != len ) {
2694       name = name.substr( 0, i );
2695       len = i;
2696     }
2697     */
2698     // cut off leading white spaces
2699     string::size_type firstChar = name.find_first_not_of(" \t");
2700     if (firstChar < name.length())
2701     {
2702       name = name.substr(firstChar);
2703     }
2704     else
2705     {
2706       name = ""; // only whitespaces there - remove them
2707     }
2708     // cut off trailing white spaces
2709     string::size_type lastChar = name.find_last_not_of(" \t");
2710     if (lastChar < name.length()) {
2711       name = name.substr(0, lastChar + 1);
2712     }
2713   }
2714   return name;
2715 }
2716
2717 //=======================================================================
2718 //function : addSupport
2719 //purpose  :
2720 //=======================================================================
2721
2722 bool GIBI_MESH_WRONLY_DRIVER::addSupport( const SUPPORT * support )
2723 {
2724   if ( !support )
2725     return false;
2726   map<const SUPPORT*,supportData>::iterator su = _supports.find( support );
2727   if ( su != _supports.end() )
2728     return ( su->second.getNumberOfTypes() > 0 );
2729
2730   if ( support->getMesh() != _mesh )
2731     throw MEDEXCEPTION(LOCALIZED(STRING("cant write support of other mesh" )));
2732
2733   MESH* mesh = (MESH*)_mesh;
2734
2735   // get sub-supports and define a support type name
2736   string supType;
2737   list<const SUPPORT*> sList;
2738   const GROUP* group = dynamic_cast< const GROUP* >(support);
2739   if ( group )
2740   {
2741     if ( group->getNumberOfTypes() > 0 || group->isOnAllElements() )
2742       sList.push_back( group );
2743     else {
2744       int iFam, nbFam = group->getNumberOfFamilies();
2745       for ( iFam = 1; iFam <= nbFam; ++iFam )
2746         sList.push_back( group->getFamily( iFam ));
2747     }
2748     supType = "group";
2749   }
2750   else
2751   {
2752     sList.push_back( support );
2753     supType = dynamic_cast< const FAMILY* >(support) ? "family" : "support";
2754   }
2755
2756   supportData & data = _supports[ support ];
2757   data._cleanName = cleanName( support->getName() );
2758
2759   // check if it is a writtable support, i.e.
2760   // nodal connectivity for a support entity exists
2761   medEntityMesh entity = support->getEntity();
2762   if ( entity != MED_NODE && !mesh->existConnectivity( MED_NODAL, entity )) {
2763     INFOS_MED("Do not save " << supType << " of entity " << entity
2764           << " named <" << data._cleanName << "> nodal connectivity not defined");
2765     return false;
2766   }
2767
2768   // fill supportData
2769   list<const SUPPORT*>::iterator sIt = sList.begin();
2770   for ( ; sIt != sList.end(); sIt++ )
2771   {
2772     bool onAll = (*sIt)->isOnAllElements();
2773     int nbTypes = 0;
2774     if ( !onAll )
2775       nbTypes = (*sIt)->getNumberOfTypes();
2776     else
2777       nbTypes = _mesh->getNumberOfTypes( entity );
2778     if ( nbTypes == 0 )
2779       continue;
2780     const medGeometryElement* types = 0;
2781     if ( !onAll )
2782       types = (*sIt)->getTypes();
2783     else if ( entity != MED_NODE )
2784       types = _mesh->getTypes( entity );
2785     for ( int iType = 0; iType < nbTypes; ++iType )
2786     {
2787       if ( types && types[ iType ] > MED_HEXA20 )
2788         continue; // poly
2789       medGeometryElement geomType = types ? types[ iType ] : MED_ALL_ELEMENTS;
2790       const int * ptrElemIDs = 0;
2791       int elemID1 = 0, nbElems = 0;
2792       if ( onAll ) {
2793         nbElems = _mesh->getNumberOfElements( entity, geomType );
2794         elemID1 = (entity == MED_NODE) ? 1 : mesh->getGlobalNumberingIndex (entity)[ iType ];
2795       }
2796       else {
2797         nbElems = (*sIt)->getNumberOfElements( geomType );
2798         ptrElemIDs = (*sIt)->getNumber( geomType );
2799       }
2800       if ( geomType == 0 || ( entity == MED_NODE ))
2801         geomType = MED_POINT1;
2802
2803       data.addTypeData( geomType, nbElems, ptrElemIDs, elemID1 );
2804     }
2805   }
2806
2807   if ( data.getNumberOfTypes() == 0 ) {
2808     INFOS_MED("Do not save " << supType << " of entity " << entity
2809           << " named <" << data._cleanName << "> no geometric types");
2810     return false;
2811   }
2812
2813   return true;
2814 }
2815
2816 //=======================================================================
2817 //function : getSupportIndex
2818 //purpose  :
2819 //=======================================================================
2820
2821 int GIBI_MESH_WRONLY_DRIVER::getSubMeshIdAndSize(const SUPPORT *        support,
2822                                                  list<pair<int,int> > & idsAndSizes) const
2823 {
2824   idsAndSizes.clear();
2825   map<const SUPPORT*,supportData>::const_iterator su = _supports.find( support );
2826   if ( su == _supports.end() )
2827     return 0;
2828
2829   supportData * data = const_cast<supportData *>( & su->second );
2830   int id = data->_id;
2831   if ( data->getNumberObjects() > data->getNumberOfTypes() )
2832     id++;
2833   supportData::typeIterator tIt = data->_types.begin();
2834   for ( ; tIt != data->_types.end(); ++tIt )
2835   {
2836     int size = 0;
2837     list< typeData >& td = tIt->second;
2838     list< typeData >::iterator tdIt = td.begin();
2839     for ( ; tdIt != td.end(); ++tdIt )
2840       size += tdIt->_nbElems;
2841     idsAndSizes.push_back( make_pair( id++, size ));
2842   }
2843   return idsAndSizes.size();
2844 }
2845
2846 // ============================================================
2847 // the class writes endl to the file as soon as <limit> fields
2848 // have been written after the last endl
2849 // ============================================================
2850
2851 class TFieldCounter
2852 {
2853   fstream& _file;
2854   int _count, _limit;
2855  public:
2856   TFieldCounter(fstream& f, int limit=0): _file(f), _limit(limit) { init(); }
2857   void init(int limit=0) // init, is done by stop() as well
2858   { if (limit) _limit = limit; _count = 0; }
2859   void operator++(int) // next
2860   { if ( ++_count == _limit ) { _file << endl; init(); }}
2861   void stop() // init() and write endl if there was no endl after the last written field
2862   { if ( _count ) _file << endl; init(); }
2863 };
2864
2865 //=======================================================================
2866 //function : writeElements
2867 //purpose  : ptrElemIDs and elemID1 provide two alternative ways of giving
2868 //           elements to write.
2869 //           If elemSet != 0 then an element is
2870 //           ( addElemInSet ? <written and added to elemSet> : <ignored if id is in elemSet>)
2871 //=======================================================================
2872
2873 void GIBI_MESH_WRONLY_DRIVER::writeElements (medGeometryElement geomType,
2874                                              list< typeData >&  typeDataList,
2875                                              const int *        nodalConnect,
2876                                              const int *        nodalConnectIndex)
2877 {
2878   // ITYPEL : type de l'鬩ment 1=point, 2=segment ?eux noeuds...
2879   // NBSOUS : nombre de sous parties dans cet objet,
2880   //          une sous partie par type d'鬩ments le composant.
2881   // NBREF : nombre de sous r馩rences. Une r馩rence est par exemple le contour
2882   // NBNOEL : nombre de noeuds par é¬©ment
2883   // NBEL : nombre d'鬩ments
2884
2885   int castemType = GIBI_MESH_DRIVER::med2gibiGeom( geomType );
2886   const char* zeroI8 = "       0"; // FORMAT(I8)
2887   unsigned nbElemNodes = geomType % 100;
2888
2889   // indices to transform MED connectivity to GIBI one
2890   vector< int > toGibiConn;
2891   toGibiConn.reserve( nbElemNodes );
2892   if ( const int * toMedConn = getGibi2MedConnectivity( geomType )) {
2893     toGibiConn.resize( nbElemNodes );
2894     for ( unsigned i = 0; i < nbElemNodes; ++i )
2895       toGibiConn[ toMedConn[ i ]] = i;
2896   }
2897   else {
2898     while ( toGibiConn.size() < nbElemNodes )
2899       toGibiConn.push_back( toGibiConn.size() );
2900   }
2901
2902   // count total nb of elements
2903   int nbElements = 0;
2904   list< typeData >::iterator td = typeDataList.begin();
2905   for ( ; td != typeDataList.end(); td++ )
2906     nbElements += td->_nbElems;
2907
2908   _gibi << setw(8) << castemType <<  // ITYPE
2909     zeroI8 <<                       // NBSOUS
2910       zeroI8 <<                     // NBREF
2911         setw(8) << nbElemNodes <<   // NBNOEL
2912           setw(8) << nbElements <<  // NBEL
2913             endl;
2914
2915   MESSAGE_MED("writeElements(): geomType=" << geomType << " nbElements= " << nbElements)
2916
2917   // L 'enregistrement donnant le num? de la couleur des é¬©ments.
2918   // * 8000 FORMAT(10I8)
2919   TFieldCounter fcount( _gibi, 10 );
2920   int iElem = 0;
2921   for ( ; iElem < nbElements; ++iElem, fcount++ )
2922     _gibi << zeroI8;
2923   fcount.stop();
2924
2925   // Tableau des connectivité³® Description du premier é¬©ment puis du deuxiè­¥...
2926   // ATTENTION il ne s'agit pas de la num?tation vraie,
2927   // il faut la faire passer par le filtre du dernier tableau de la pile num? 32.
2928   //int nbSkipped = 0;
2929
2930   for ( td = typeDataList.begin(); td != typeDataList.end(); td++ )
2931   {
2932     for ( int i = 0; i < td->_nbElems; i++ )
2933     {
2934       iElem = td->_ptrElemIDs ? td->_ptrElemIDs[ i ] : td->_elemID1 + i;
2935       if ( geomType == MED_POINT1 )
2936       {
2937         _gibi << setw(8) << iElem;
2938         fcount++;
2939       }
2940       else
2941       {
2942         int nodeId = nodalConnectIndex[ iElem - 1 ] - 1;
2943         for ( unsigned iNode = 0; iNode < nbElemNodes; ++iNode, fcount++ ) {
2944           _gibi << setw(8) << nodalConnect[ nodeId + toGibiConn[ iNode ]];
2945         }
2946       }
2947     }
2948   }
2949
2950   fcount.stop();
2951 }
2952
2953 //=======================================================================
2954 //function : addName
2955 //purpose  : make name uppercase and shorter than 9, add it to nameNbMap,
2956 //           raise if not unique
2957 //=======================================================================
2958 /*
2959 void GIBI_MESH_WRONLY_DRIVER::addName(map<string,int>& nameMap,
2960                                       string&          theName,
2961                                       int              index,
2962                                       string           prefix)
2963 {
2964   string name = cleanName( theName );
2965   if ( !name.empty() ) {
2966     int len = name.length();
2967 #ifdef THROW_ON_BAD_NAME
2968     if ( len > 8 )
2969       throw MEDEXCEPTION(STRING("Can't write name longer than 8: ") << name );
2970
2971     for ( int i = 0; i < len; ++i )
2972       name[i] = toupper( name[i] );
2973     if ( ! nameMap.insert( make_pair( name, index )).second )
2974       throw MEDEXCEPTION(STRING("Can't write not unique name: ") << name );
2975 #else
2976     bool ok = ( len <= 8 && len > 0 );
2977     if ( ok ) {
2978       for ( int i = 0; i < len; ++i )
2979         name[i] = toupper( name[i] );
2980       ok = nameMap.insert( make_pair( name, index )).second;
2981     }
2982     if ( !ok ) {
2983       char *str=new char[ prefix.size() + 13 ];
2984       int j = 1;
2985       do {
2986         sprintf( str, "%s_%d", prefix.c_str(), nameMap.size()+j );
2987         ok = nameMap.insert( make_pair( str, index )).second;
2988         j++;
2989       } while ( !ok );
2990       INFOS_MED( "Save <" << name << "> as <" << str << ">");
2991       delete [] str;
2992     }
2993 #endif
2994   }
2995 }
2996 */
2997
2998 // Converts names like:
2999 // MED:
3000 //   TEMPERATURE_FLUIDE
3001 //   TEMPERATURE_SOLIDE
3002 //   PRESSION
3003 //   NU
3004 //   VOLUM001
3005 //   VOLUMOFOBJECT
3006 //   VOLUM002
3007 //
3008 // GIBI:
3009 //   TEMPE001
3010 //   TEMPE002
3011 //   PRESSION
3012 //   NU
3013 //   VOLUM001
3014 //   VOLUM003
3015 //   VOLUM002
3016 void GIBI_MESH_WRONLY_DRIVER::addName (map<string,int>& nameMap,
3017                                        map<string,int>& namePrefixesMap,
3018                                        const string&    theName,
3019                                        int              index)
3020 {
3021   string name = cleanName(theName);
3022   int ind = index;
3023
3024   if (!name.empty()) {
3025     int len = name.length();
3026     for (int i = 0; i < len; ++i)
3027       name[i] = toupper(name[i]);
3028
3029     bool doResave = false; // only for tracing
3030
3031     // I. Save a short name as it is
3032     if (len <= 8) {
3033       INFOS_MED("Save <" << theName << "> as <" << name << ">");
3034
3035       map<string,int>::iterator it = nameMap.find(name);
3036       if (it != nameMap.end()) {
3037         // There is already such name in the map.
3038
3039         // a. Replace in the map the old pair by the current one
3040         int old_ind = nameMap[name];
3041         nameMap[name] = ind;
3042         // b. Rebuild the old pair (which was in the map,
3043         //    it seems to be built automatically by step II)
3044         ind = old_ind;
3045         // continue with step II
3046         doResave = true; // only for tracing
3047       }
3048       else {
3049         // Save in the map
3050         nameMap.insert(make_pair(name, ind));
3051
3052         // Update loc_index for this name (if last free characters represents a number)
3053         // to avoid conflicts with long names, same in first 5 characters
3054         if (len == 8) {
3055           int new_loc_index = atoi(name.c_str() + 5);
3056           if (new_loc_index > 0) {
3057             // prefix
3058             char str [6];
3059             strncpy(str, name.c_str(), 5);
3060             str[5] = '\0';
3061
3062             if (namePrefixesMap.find(str) != namePrefixesMap.end()) {
3063               int old_loc_index = namePrefixesMap[str];
3064               if (new_loc_index < old_loc_index) new_loc_index = old_loc_index;
3065             }
3066             namePrefixesMap[str] = new_loc_index;
3067           }
3068         }
3069         return;
3070       }
3071     } // if (len <= 8)
3072
3073     // II. Cut long name and add a numeric suffix
3074
3075     // first 5 or less characters of the name
3076     if (len > 5) len = 5;
3077     char str [9];
3078     str[8] = '\0';
3079     int addr = 0;
3080     strncpy(str, name.c_str(), len);
3081     addr = len;
3082     str[addr] = '\0';
3083
3084     // numeric suffix
3085     int loc_index = 1;
3086     if (namePrefixesMap.find(str) != namePrefixesMap.end())
3087       loc_index = namePrefixesMap[str] + 1;
3088     namePrefixesMap[str] = loc_index;
3089
3090     if (loc_index > 999)
3091       throw MEDEXCEPTION(STRING("Can't write not unique name: ") << name);
3092
3093     if (loc_index < 100) {
3094       str[addr] = '0';
3095       addr++;
3096     }
3097     if (loc_index < 10) {
3098       str[addr] = '0';
3099       addr++;
3100     }
3101     sprintf(str + addr, "%d", loc_index);
3102
3103     nameMap.insert(make_pair(str, ind));
3104     if (doResave) {
3105       INFOS_MED("Resave previous <" << name << "> as <" << str << ">");
3106     }
3107     else {
3108       INFOS_MED("Save <" << theName << "> as <" << str << ">");
3109     }
3110   }
3111 }
3112
3113 //=======================================================================
3114 //function : writeNames
3115 //purpose  :
3116 //=======================================================================
3117
3118 void GIBI_MESH_WRONLY_DRIVER::writeNames( map<string,int>& nameNbMap )
3119 {
3120   // La pile num? 1 est celle des objets de type maillage.
3121   // La ligne suivante donne le nom des objets maillages sauvé³®
3122   // * 8001       FORMAT(8(1X,A8))
3123   if ( !nameNbMap.empty() )
3124   {
3125     TFieldCounter fcount( _gibi, 8 );
3126     _gibi << left;
3127     map<string,int>::iterator nameNbIt = nameNbMap.begin();
3128     for ( ; nameNbIt != nameNbMap.end(); nameNbIt++, fcount++ ) {
3129       _gibi << " " << setw(8) << nameNbIt->first;
3130     }
3131     fcount.stop();
3132     _gibi << right;
3133     // La ligne suivante donne les num?s d'ordre, dans la pile,
3134     // des objets nomm?cit?pr飩demment.
3135     // *  8000 FORMAT(10I8)
3136     nameNbIt = nameNbMap.begin();
3137     for ( fcount.init(10); nameNbIt != nameNbMap.end(); nameNbIt++, fcount++ )
3138       _gibi << setw(8) << nameNbIt->second;
3139     fcount.stop();
3140   }
3141 }
3142
3143 //=======================================================================
3144 //function : writeSupportsAndMesh
3145 //purpose  :
3146 //=======================================================================
3147
3148 void GIBI_MESH_WRONLY_DRIVER::writeSupportsAndMesh(list<nameGIBItoMED>& listGIBItoMED_mail)
3149 {
3150   const char * LOC = "void GIBI_MESH_WRONLY_DRIVER::writeSupportsAndMesh() ";
3151   BEGIN_OF_MED(LOC);
3152
3153   if (_status!=MED_OPENED)
3154     throw MEDEXCEPTION(LOCALIZED(STRING(LOC) << "file " << _fileName<<  " is not opened." ));
3155   if (!_mesh)
3156     throw MEDEXCEPTION(LOCALIZED(STRING(LOC) << "can't write a NULL mesh" ));
3157
3158   const MESH* mesh = _mesh->convertInMESH();
3159   AutoDeref meshDeref( mesh );
3160
3161   if (!mesh->getConnectivityptr()) 
3162     throw MEDEXCEPTION(LOCALIZED(STRING(LOC) << "can't write a mesh with NULL connectivity" ));
3163
3164   // fill _supports with families and groups
3165   medEntityMesh entity;
3166   for (entity=MED_CELL; entity<MED_ALL_ENTITIES; ++entity)
3167   {
3168     int i, nb = _mesh->getNumberOfGroups(entity);
3169     for ( i = 1; i <= nb; ++i )
3170       addSupport( _mesh->getGroup( entity, i ));
3171 //     nb = _mesh->getNumberOfFamilies(entity);
3172 //     for ( i = 1; i <= nb; ++i )
3173 //       addSupport( _mesh->getFamily( entity, i ));
3174   }
3175
3176   // --------------------------------------------------------------------
3177   // Count total nb of objects: an object per an element type in support
3178   // plus an object per an element type not used in _supports.
3179   // Collect object names
3180   // --------------------------------------------------------------------
3181
3182   vector<int> nbSuppElemsByType(MED_HEXA20+1,0);
3183   map<string,int> nameNbMap;
3184   map<string,int> namePrefixMap;
3185   map<const SUPPORT*,supportData>::iterator supIt = _supports.begin();
3186   int i, nb_objects = 0;
3187   for ( ; supIt != _supports.end(); supIt++ )
3188   {
3189     supportData & data = supIt->second;
3190     int nbSupObj = data.getNumberObjects();
3191     if ( nbSupObj == 0 )
3192       continue;
3193     data._id = nb_objects + 1;
3194     nb_objects += nbSupObj;
3195
3196     //addName( nameNbMap, data._cleanName, data._id, "C" );
3197     addName(nameNbMap, namePrefixMap, data._cleanName, data._id);
3198
3199     // IMP 0020434: mapping GIBI names to MED names
3200     nameGIBItoMED aMEDName;
3201     aMEDName.gibi_pile = PILE_SOUS_MAILLAGE;
3202     aMEDName.gibi_id = data._id;
3203     aMEDName.med_name = data._cleanName;
3204     listGIBItoMED_mail.push_back(aMEDName);
3205
3206     MESSAGE_MED( "obj " << data._id << " " << data._cleanName);
3207
3208     // count elements: take into account supports on all elements and families only
3209     const SUPPORT* support = supIt->first;
3210     if ( support->isOnAllElements() || dynamic_cast< const FAMILY* >( support ))
3211     {
3212       supportData::typeIterator tIt = data._types.begin();
3213       for ( ; tIt != data._types.end(); ++tIt )
3214         if ( support->isOnAllElements() )
3215         {
3216           nbSuppElemsByType[ tIt->first ] = INT_MAX / 100;
3217         }
3218         else
3219         {
3220           list< typeData >& td = tIt->second;
3221           list< typeData >::iterator tdIt = td.begin();
3222           for ( ; tdIt != td.end(); ++tdIt )
3223             nbSuppElemsByType[ tIt->first] += tdIt->_nbElems;
3224         }
3225     }
3226   }
3227
3228   // count types of mesh elements that are not all in _supports
3229   int iType, nbTypes;
3230   entity = mesh->getConnectivityptr()->getEntity();
3231   for ( ; entity < MED_NODE; entity++ )
3232   {
3233     nbTypes = _mesh->getNumberOfTypes( entity );
3234     if ( nbTypes == 0 || !mesh->existConnectivity( MED_NODAL, entity ))
3235       continue;
3236     const medGeometryElement* types = _mesh->getTypes( entity );
3237     for ( iType = 0; iType < nbTypes; ++iType )
3238     {
3239       int nbElemInSups = nbSuppElemsByType[ types[ iType ]];
3240       int nbElemInMesh = _mesh->getNumberOfElements(entity, types[ iType ]);
3241       if ( nbElemInSups < nbElemInMesh ) {
3242         nb_objects++;
3243         nbSuppElemsByType[ types[ iType ]] = -1; // to keep written elements of _supports
3244       }
3245     }
3246   }
3247
3248   // ------------
3249   // Write file
3250   // ------------
3251
3252   // Premier paquet dont le nombre de lignes ne varie pas.
3253   // On y trouve des indications g鮩rales.
3254   const int dim = _mesh->getSpaceDimension();
3255   _gibi << " ENREGISTREMENT DE TYPE   4" << endl;
3256   _gibi << " NIVEAU  15 NIVEAU ERREUR   0 DIMENSION   " << dim <<endl;
3257   _gibi << " DENSITE  .00000E+00" << endl;
3258   _gibi << " ENREGISTREMENT DE TYPE   7" << endl;
3259   _gibi << " NOMBRE INFO CASTEM2000   8" <<endl;
3260   _gibi << " IFOUR  -1 NIFOUR   0 IFOMOD  -1 IECHO   1 IIMPI   0 IOSPI   0 ISOTYP   1" << endl;
3261   _gibi << " NSDPGE     0" << endl;
3262
3263   // Deuxiè­¥ paquet qui d馩nit toutes les piles
3264   // (une pile par type d'objet et certaines piles en plus).
3265   // Un enregistrement de type 2 pr鶩ent de l'飲iture d'une nouvelle pile,
3266   // celui de type 5 pr鶩ent de la fin.
3267   // * 800   FORMAT (' ENREGISTREMENT DE TYPE', I4)
3268   _gibi << " ENREGISTREMENT DE TYPE   2" << endl;
3269   // * 801     FORMAT(' PILE NUMERO',I4,'NBRE OBJETS NOMMES',I8,'NBRE OBJETS',I8)
3270   _gibi << " PILE NUMERO   1NBRE OBJETS NOMMES" << setw(8) << nameNbMap.size() <<
3271     "NBRE OBJETS" << setw(8) << nb_objects <<endl;
3272
3273   writeNames( nameNbMap );
3274
3275   // Passage ?a description des objets les uns aprè³ les autres.
3276   // Le premier enregistrement de chaque objet est composé ¤e 5 nombres repré³¥ntant :
3277   // ITYPEL : type de l'鬩ment 1=point, 2=segment ?eux noeuds...
3278   // NBSOUS : nombre de sous parties dans cet objet,
3279   //          une sous partie par type d'鬩ments le composant.
3280   // NBREF : nombre de sous r馩rences. Une r馩rence est par exemple le contour
3281   // NBNOEL : nombre de noeuds par é¬©ment
3282   // NBEL : nombre d'鬩ments
3283   // Si ITYPEL=0 alors NBSOUS diffé²¥nt de z?. Dans ce cas on lira la liste des positions,
3284   // dans la pile des objets, des sous parties le composant.
3285   // Si NBSOUS=0, NBNOEL et NBEL sont diffé²¥nts de z?, on trouve, au besoin,
3286   // la liste des r馩rences , les num?s des couleurs puis les connectivité³®
3287
3288   TFieldCounter fcount( _gibi, 10 );
3289   const char* zeroI8 = "       0"; // FORMAT(I8)
3290   for ( supIt = _supports.begin(); supIt != _supports.end(); supIt++ )
3291   {
3292     supportData & data = supIt->second;
3293     int nbSupObj = data.getNumberObjects();
3294     if ( nbSupObj == 0 )
3295       continue;
3296     MESSAGE_MED("support " << data._id << "<" << data._cleanName << ">");
3297
3298     // write a compound object
3299     int nbTypes = data.getNumberOfTypes();
3300     if ( nbSupObj > nbTypes )
3301     {
3302       _gibi << zeroI8 << setw(8) << nbTypes << zeroI8 << zeroI8 << zeroI8 << endl;
3303       for ( int i_sub = 1; i_sub <= nbTypes; ++i_sub, fcount++ )
3304         _gibi << setw(8) << ( data._id + i_sub );
3305       fcount.stop();
3306     }
3307
3308     // write components
3309     entity = supIt->first->getEntity();
3310     const int * nodalConnect = 0, * nodalConnectIndex = 0;
3311     if ( entity != MED_NODE ) {
3312       nodalConnect = mesh->getConnectivity (MED_NODAL,entity,MED_ALL_ELEMENTS);
3313       nodalConnectIndex = mesh->getConnectivityIndex (MED_NODAL,entity);
3314     }
3315     supportData::typeIterator tIt = data._types.begin();
3316     for ( ; tIt != data._types.end(); ++tIt )
3317     {
3318       writeElements (tIt->first,
3319                      tIt->second,
3320                      nodalConnect,
3321                      nodalConnectIndex);
3322     }
3323   }  // loop on _supports
3324
3325   // Write elements that are not in _supports
3326
3327   supportData data;
3328   entity = mesh->getConnectivityptr()->getEntity();
3329   for ( ; entity < MED_NODE; entity++ )
3330   {
3331     int nbTypes = _mesh->getNumberOfTypes( entity );
3332     if ( nbTypes == 0 || !mesh->existConnectivity( MED_NODAL, entity ))
3333       continue;
3334     const medGeometryElement* types = _mesh->getTypes( entity );
3335     const int * nbIndex = mesh->getGlobalNumberingIndex (entity);
3336     const int * nodalConnect = 0, * nodalConnectIndex = 0;
3337     nodalConnect = mesh->getConnectivity (MED_NODAL,entity,MED_ALL_ELEMENTS);
3338     nodalConnectIndex = mesh->getConnectivityIndex (MED_NODAL,entity);
3339
3340     for ( int iType = 1; iType <= nbTypes; ++iType )
3341     {
3342       int nbElements = nbIndex[ iType ] - nbIndex[ iType - 1 ];
3343       medGeometryElement geomType = types[ iType - 1 ];
3344       if ( nbSuppElemsByType[ geomType ] >= nbElements )
3345         continue; // all elements are written with _supports
3346
3347       int elemId1 = nbIndex[ iType - 1 ];
3348       data.addTypeData( geomType, nbElements, 0, elemId1 );
3349
3350       writeElements (geomType,
3351                      data._types[ geomType ],
3352                      nodalConnect,
3353                      nodalConnectIndex);
3354     }
3355   }
3356
3357   // D颵t de la pile 32 (celle des points)
3358
3359   int nbNodes = _mesh->getNumberOfNodes();
3360   _gibi << " ENREGISTREMENT DE TYPE   2" << endl;
3361   _gibi << " PILE NUMERO  32NBRE OBJETS NOMMES       0" <<
3362     "NBRE OBJETS" << setw(8) << nbNodes << endl;
3363   // Liste des noms de points
3364   // * 8001       FORMAT(8(1X,A8))
3365   // No named nodes
3366   // suit le nombre de noeuds
3367   _gibi << setw(8) << nbNodes << endl;
3368   // Le tableau suivant donne le filtre pour avoir le vrai num? des noeuds
3369   // appartenant aux é¬©ments d飲its. Par exemple, si un é¬©ment, d飲it
3370   // dans la pile 1, fait r馩rence ?n num? de noeud é§¡l ? il faut le
3371   // mettre é§¡l ?2
3372   // * 8000 FORMAT(10I8)
3373   for ( i = 0; i < nbNodes; ++i, fcount++ )
3374     _gibi << setw(8) << i + 1;
3375   fcount.stop();
3376
3377   // D颵t de pile 33 (celle des configurations (coordonn?))
3378   _gibi << " ENREGISTREMENT DE TYPE   2" << endl;
3379   _gibi << " PILE NUMERO  33NBRE OBJETS NOMMES       0NBRE OBJETS       1" << endl;
3380   // Suit le nombre de points dont on donne les coordonn?
3381   int nbValues = nbNodes * ( dim + 1 );
3382   _gibi << setw(8) << nbValues << endl;
3383   // Les coordonn? sont donn? par noeuds. D'abord le premier puis le deuxiè­¥...
3384   // Pour chaque noeuds, on donne les 2 ou 3 coordonn? plus la densité £ourante
3385   // au moment de sa cré¡´ion.
3386   // * 8003   FORMAT(1P,3E22.14)
3387   _gibi.precision(14);
3388   _gibi.setf( ios_base::scientific, ios_base::floatfield );
3389   _gibi.setf( ios_base::uppercase );
3390   const double * coords = mesh->getCoordinates(MED_FULL_INTERLACE);
3391   int j = 0;
3392   const double precision = 1.e-99; // PAL12077
3393   for ( fcount.init(3),i = 0; i < nbNodes; ++i, j += dim )
3394   {
3395     for ( int iCoord = 0; iCoord < dim; ++iCoord, fcount++ ) {
3396       double coo = coords[ j + iCoord ];
3397       bool  zero = ( -precision < coo && coo < precision );
3398       _gibi << setw(22) << ( zero ? 0.0 : coo );
3399     }
3400     _gibi << setw(22) << 0.0; // densite
3401     fcount++;
3402   }
3403   fcount.stop();
3404
3405   END_OF_MED(LOC);
3406 }
3407
3408 //=======================================================================
3409 //function : writeMEDNames
3410 //purpose  :
3411 //=======================================================================
3412 void GIBI_MESH_WRONLY_DRIVER::writeMEDNames (const list<nameGIBItoMED>& listGIBItoMED_mail,
3413                                              const list<nameGIBItoMED>& listGIBItoMED_cham,
3414                                              const list<nameGIBItoMED>& listGIBItoMED_comp)
3415 {
3416   // IMP 0020434: mapping GIBI names to MED names
3417   // Store correspondence between GIBI and MED names
3418   // as one PILE_STRINGS and one PILE_TABLES
3419   // (in three tables: MED_MAIL, MED_CHAM and MED_COMP)
3420
3421   int nbNames_mail = listGIBItoMED_mail.size();
3422   int nbNames_cham = listGIBItoMED_cham.size();
3423   int nbNames_comp = listGIBItoMED_comp.size();
3424
3425   int nbTables = 0;
3426   if (nbNames_mail) nbTables++;
3427   if (nbNames_cham) nbTables++;
3428   if (nbNames_comp) nbTables++;
3429
3430   if (!nbTables)
3431     return;
3432
3433   // The whole string (concatenated names)
3434   string theWholeString;
3435   list<int> theOffsets;
3436   int currOffset = 0;
3437
3438   // The TABLE PILE
3439   // * 800   FORMAT (' ENREGISTREMENT DE TYPE', I4)
3440   _gibi << " ENREGISTREMENT DE TYPE   2" << endl;
3441   // * 801     FORMAT(' PILE NUMERO',I4,'NBRE OBJETS NOMMES',I8,'NBRE OBJETS',I8)
3442   _gibi << " PILE NUMERO  10NBRE OBJETS NOMMES" << setw(8) << nbTables <<
3443     "NBRE OBJETS" << setw(8) << nbTables << endl; // <nbTables> named tables
3444   // Table names
3445   if (nbNames_mail)
3446     _gibi << " MED_MAIL";
3447   if (nbNames_cham)
3448     _gibi << " MED_CHAM";
3449   if (nbNames_comp)
3450     _gibi << " MED_COMP";
3451   _gibi << endl;
3452   // Table indices
3453   _gibi << setw(8) << 1;
3454   if (nbTables > 1) _gibi << setw(8) << 2;
3455   if (nbTables > 2) _gibi << setw(8) << 3;
3456   _gibi << endl;
3457
3458   int istr = 1;
3459
3460   // Table MED_MAIL
3461   if (nbNames_mail) {
3462     // Provide unique MED names, to exclude conflicts on reading saved files
3463     // (use case: read fra.med, save it to GIBI, read it from GIBI,
3464     // save to MED again -> this new MED file is not readable)
3465     set<string> medUniqueNames;
3466
3467     _gibi << setw(8) << nbNames_mail*4 << endl; // Nb of table values
3468
3469     TFieldCounter fcount1 (_gibi, 10);
3470     _gibi << right;
3471     list<nameGIBItoMED>::const_iterator itGIBItoMED = listGIBItoMED_mail.begin();
3472     for (; itGIBItoMED != listGIBItoMED_mail.end(); itGIBItoMED++, istr++) {
3473       // PILE of i-th key(med name)
3474       _gibi << setw(8) << 27; fcount1++; // PILE_STRINGS number is 27
3475       // ID of i-th key(med name)
3476       _gibi << setw(8) << istr; fcount1++;
3477
3478       // PILE of i-th value(gibi name)
3479       _gibi << setw(8) << itGIBItoMED->gibi_pile; fcount1++; // PILE_SOUS_MAILLAGE number is 1
3480       // ID of i-th value(gibi name)
3481       _gibi << setw(8) << itGIBItoMED->gibi_id; fcount1++;
3482
3483       // check MED name to be unique
3484       string aMedName = itGIBItoMED->med_name;
3485       if (!medUniqueNames.insert(aMedName).second) {
3486         string aMedNameNew;
3487         int ind = 1;
3488         char strInd [32];
3489         do {
3490           sprintf(strInd, "_%d", ind++);
3491           aMedNameNew = aMedName + strInd;
3492         } while (!medUniqueNames.insert(aMedNameNew).second);
3493         aMedName = aMedNameNew;
3494       }
3495
3496       // add to the string
3497       theWholeString += aMedName; // MED name
3498
3499       // add an offset
3500       currOffset += aMedName.length();
3501       theOffsets.push_back(currOffset);
3502     }
3503     fcount1.stop();
3504   }
3505
3506   // Table MED_CHAM
3507   if (nbNames_cham) {
3508     // Provide unique MED names, to exclude conflicts on reading saved files
3509     // (use case: read fra.med, save it to GIBI, read it from GIBI,
3510     // save to MED again -> this new MED file is not readable)
3511     set<string> medUniqueNames;
3512
3513     _gibi << setw(8) << nbNames_cham*4 << endl; // Nb of table values
3514
3515     TFieldCounter fcount1 (_gibi, 10);
3516     _gibi << right;
3517     list<nameGIBItoMED>::const_iterator itGIBItoMED = listGIBItoMED_cham.begin();
3518     for (; itGIBItoMED != listGIBItoMED_cham.end(); itGIBItoMED++, istr++) {
3519       // PILE of i-th key(med name)
3520       _gibi << setw(8) << 27; fcount1++; // PILE_STRINGS number is 27
3521       // ID of i-th key(med name)
3522       _gibi << setw(8) << istr; fcount1++;
3523
3524       // PILE of i-th value(gibi name)
3525       // PILE_NODES_FIELD number is 2, PILE_FIELD number is 39
3526       _gibi << setw(8) << itGIBItoMED->gibi_pile; fcount1++;
3527       // ID of i-th value(gibi name)
3528       _gibi << setw(8) << itGIBItoMED->gibi_id; fcount1++;
3529
3530       // check MED name to be unique
3531       string aMedName = itGIBItoMED->med_name;
3532       if (!medUniqueNames.insert(aMedName).second) {
3533         string aMedNameNew;
3534         int ind = 1;
3535         char strInd [32];
3536         do {
3537           sprintf(strInd, "_%d", ind++);
3538           aMedNameNew = aMedName + strInd;
3539         } while (!medUniqueNames.insert(aMedNameNew).second);
3540         aMedName = aMedNameNew;
3541       }
3542
3543       // add to the string
3544       theWholeString += aMedName; // MED name
3545
3546       // add an offset
3547       currOffset += aMedName.length();
3548       theOffsets.push_back(currOffset);
3549     }
3550     fcount1.stop();
3551   }
3552
3553   // Table MED_COMP
3554   if (nbNames_comp) {
3555     // for components, both key and value (long and short name) is in the STRING PILE
3556
3557     _gibi << setw(8) << nbNames_comp*4 << endl; // Nb of table values
3558
3559     TFieldCounter fcount1 (_gibi, 10);
3560     _gibi << right;
3561     list<nameGIBItoMED>::const_iterator itGIBItoMED = listGIBItoMED_comp.begin();
3562     for (; itGIBItoMED != listGIBItoMED_comp.end(); itGIBItoMED++, istr+=2) {
3563       // PILE of i-th key(med name)
3564       _gibi << setw(8) << 27; fcount1++; // PILE_STRINGS number is 27
3565       // ID of i-th key(med name)
3566       _gibi << setw(8) << istr; fcount1++;
3567
3568       // PILE of i-th value(gibi name)
3569       _gibi << setw(8) << 27; fcount1++; // PILE_STRINGS number is 27
3570       // ID of i-th value(gibi name)
3571       _gibi << setw(8) << istr + 1; fcount1++;
3572
3573       // add to the string
3574       string aMedName  = itGIBItoMED->med_name;
3575       string aGibiName = itGIBItoMED->gibi_name;
3576       theWholeString += aMedName; // MED name
3577       theWholeString += aGibiName; // GIBI name
3578
3579       // add offsets
3580       currOffset += aMedName.length();
3581       theOffsets.push_back(currOffset);
3582       currOffset += aGibiName.length();
3583       theOffsets.push_back(currOffset);
3584     }
3585     fcount1.stop();
3586   }
3587
3588   int nbNames = nbNames_mail + nbNames_cham + 2 * nbNames_comp; // tmp
3589
3590   // The STRING PILE
3591   // * 800   FORMAT (' ENREGISTREMENT DE TYPE', I4)
3592   _gibi << " ENREGISTREMENT DE TYPE   2" << endl;
3593   // * 801     FORMAT(' PILE NUMERO',I4,'NBRE OBJETS NOMMES',I8,'NBRE OBJETS',I8)
3594   _gibi << " PILE NUMERO  27NBRE OBJETS NOMMES" << setw(8) << 0 << // No named strings
3595     "NBRE OBJETS" << setw(8) << nbNames << endl;
3596
3597   // Write IDs
3598   //TFieldCounter fcount2 (_gibi, 10);
3599   //_gibi << right;
3600   //for (int jj = 1; jj <= nbNames; jj++) {
3601   //  _gibi << setw(8) << jj; fcount2++;
3602   //}
3603   //fcount2.stop();
3604
3605   // <LENGTH>     <NB>
3606   _gibi << setw(8) << theWholeString.length()
3607         << setw(8) << nbNames << endl;
3608
3609   // Write the whole string
3610   const int fixedLength = 71;
3611   int aPos = 0;
3612   int aLen = theWholeString.length();
3613   for (; aPos < aLen; aPos += fixedLength) {
3614     _gibi << setw(72) << theWholeString.substr(aPos, fixedLength) << endl;
3615   } while (aPos < aLen);
3616
3617   // Write the offsets
3618   TFieldCounter fcount3 (_gibi, 10);
3619   _gibi << right;
3620   list<int>::iterator offsetIt = theOffsets.begin();
3621   for (; offsetIt != theOffsets.end(); offsetIt++) {
3622     _gibi << setw(8) << (*offsetIt); fcount3++;
3623   }
3624   fcount3.stop();
3625 }
3626
3627 //=======================================================================
3628 //function : writeLastRecord
3629 //purpose  :
3630 //=======================================================================
3631
3632 void GIBI_MESH_WRONLY_DRIVER::writeLastRecord()
3633 {
3634   _gibi << " ENREGISTREMENT DE TYPE   5" << endl;
3635   _gibi << "LABEL AUTOMATIQUE :   1" << endl;
3636 }
3637
3638 /*--------------------- RDWR PART -------------------------------*/
3639
3640 GIBI_MESH_RDWR_DRIVER::GIBI_MESH_RDWR_DRIVER()
3641   :GIBI_MESH_DRIVER(), GIBI_MESH_RDONLY_DRIVER(), GIBI_MESH_WRONLY_DRIVER()
3642 {
3643 }
3644 GIBI_MESH_RDWR_DRIVER::GIBI_MESH_RDWR_DRIVER(const string & fileName, MESH * ptrMesh):
3645   GIBI_MESH_DRIVER(fileName,ptrMesh,RDWR),
3646   GIBI_MESH_RDONLY_DRIVER(fileName,ptrMesh),
3647   GIBI_MESH_WRONLY_DRIVER(fileName,ptrMesh)
3648 {
3649   MESSAGE_MED("GIBI_MESH_RDWR_DRIVER::GIBI_MESH_RDWR_DRIVER(const string & fileName, MESH * ptrMesh) has been created");
3650 }
3651 GIBI_MESH_RDWR_DRIVER::GIBI_MESH_RDWR_DRIVER(const GIBI_MESH_RDWR_DRIVER & driver):
3652   GIBI_MESH_DRIVER(driver),
3653   GIBI_MESH_RDONLY_DRIVER(driver),
3654   GIBI_MESH_WRONLY_DRIVER(driver)
3655 {
3656   MESSAGE_MED("GIBI_MESH_RDWR_DRIVER::GIBI_MESH_RDWR_DRIVER(driver) has been created");
3657 }
3658 GIBI_MESH_RDWR_DRIVER::~GIBI_MESH_RDWR_DRIVER() {
3659   MESSAGE_MED("GIBI_MESH_RDWR_DRIVER::GIBI_MESH_RDWR_DRIVER(const string & fileName, MESH * ptrMesh) has been destroyed");
3660 }
3661 GENDRIVER * GIBI_MESH_RDWR_DRIVER::copy(void) const
3662 {
3663   const char* LOC = "GIBI_MESH_RDWR_DRIVER::copy()";
3664   BEGIN_OF_MED(LOC);
3665   GENDRIVER * driver = new GIBI_MESH_RDWR_DRIVER(*this);
3666   END_OF_MED(LOC);
3667   return driver;
3668 }
3669 void GIBI_MESH_RDWR_DRIVER::write(void) const
3670   throw (MEDEXCEPTION)
3671 {
3672   GIBI_MESH_RDWR_DRIVER * me = const_cast<GIBI_MESH_RDWR_DRIVER *>(this);
3673   me->GIBI_MESH_WRONLY_DRIVER::open();
3674   me->GIBI_MESH_WRONLY_DRIVER::write();
3675   me->GIBI_MESH_WRONLY_DRIVER::close();
3676 }
3677 void GIBI_MESH_RDWR_DRIVER::read (void)
3678   throw (MEDEXCEPTION)
3679 {
3680   const char* LOC = "GIBI_MESH_RDWR_DRIVER::read()";
3681   BEGIN_OF_MED(LOC);
3682   GIBI_MESH_RDONLY_DRIVER::open();
3683   GIBI_MESH_RDONLY_DRIVER::read();
3684   GIBI_MESH_RDONLY_DRIVER::close();
3685   END_OF_MED(LOC);
3686 }
3687 void GIBI_MESH_RDWR_DRIVER::open()
3688   // throw (MEDEXCEPTION)
3689 {
3690 }
3691 void GIBI_MESH_RDWR_DRIVER::close()
3692   // throw (MEDEXCEPTION)
3693 {
3694 }
3695
3696 //============================== ====================================================
3697 //============================== FIELD Reading Driver ==============================
3698 //============================== ====================================================
3699
3700 GIBI_MED_RDONLY_DRIVER::GIBI_MED_RDONLY_DRIVER():GIBI_MESH_RDONLY_DRIVER(),_fields(0)
3701 {
3702 }
3703 GIBI_MED_RDONLY_DRIVER::GIBI_MED_RDONLY_DRIVER(const string & fileName, vector<FIELD_*>& ptrFields):
3704   GIBI_MESH_RDONLY_DRIVER(fileName,NULL), _fields( &ptrFields )
3705 {
3706   MESSAGE_MED("GIBI_MED_RDONLY_DRIVER(const string & fileName, vector<FIELD_*>&) has been created");
3707   _fileName = fileName;
3708   _accessMode = RDONLY;
3709 }
3710 GIBI_MED_RDONLY_DRIVER::GIBI_MED_RDONLY_DRIVER(const GIBI_MED_RDONLY_DRIVER & driver):
3711   GIBI_MESH_RDONLY_DRIVER( driver ), _fields( driver._fields )
3712 {
3713 }
3714
3715 GIBI_MED_RDONLY_DRIVER::~GIBI_MED_RDONLY_DRIVER()
3716 {
3717   if ( _mesh )
3718     _mesh->removeReference();
3719 }
3720 GENDRIVER * GIBI_MED_RDONLY_DRIVER::copy ( void ) const
3721 {
3722   return new GIBI_MED_RDONLY_DRIVER(*this);
3723 }
3724
3725 //=======================================================================
3726 //function : read
3727 //purpose  :
3728 //=======================================================================
3729
3730 void GIBI_MED_RDONLY_DRIVER::read ( void ) throw (MEDEXCEPTION)
3731 {
3732   const char * LOC = "GIBI_MED_RDONLY_DRIVER::read() : ";
3733   BEGIN_OF_MED(LOC);
3734
3735   if (_status!=MED_OPENED)
3736     throw MEDEXCEPTION(LOCALIZED(STRING(LOC) << "file " << _fileName<<" is not opened." ));
3737
3738   _mesh = new MESH;
3739
3740   _intermediateMED medi;
3741   try {
3742     if ( !readFile( &medi, true ) )
3743       return;
3744
3745     //MESSAGE_MED(LOC <<  medi );
3746     fillMesh( &medi );
3747     MESSAGE_MED(LOC << "GIBI_MED_RDONLY_DRIVER::read : RESULTATS STRUCTURE INTERMEDIAIRES : ");
3748     MESSAGE_MED(LOC <<  medi );
3749
3750     list< FIELD_* > fields;
3751     medi.getFields( fields );
3752     updateSupports(); // create families from groups etc.
3753     MESSAGE_MED( "nb fields: " << fields.size() );
3754
3755     if ( _mesh->getName().empty() )
3756       _mesh->setName( "MESH" );
3757
3758     list< FIELD_* >::iterator it = fields.begin();
3759     for ( ; it != fields.end(); it++ )
3760     {
3761       FIELD_* fld = *it;
3762       int nbComponents = fld->getNumberOfComponents();
3763       if(nbComponents>0) {
3764         UNIT* compoUnits = new UNIT[nbComponents];
3765         string* MEDcompoUnits = new string[nbComponents];
3766         for(int l = 0; l<nbComponents; l++) {
3767           compoUnits[l] = UNIT("", "");
3768           MEDcompoUnits[l] = "";
3769         }
3770         fld->setComponentsUnits(compoUnits);
3771         fld->setMEDComponentsUnits(MEDcompoUnits);
3772         delete [] compoUnits;
3773         delete [] MEDcompoUnits;
3774       }
3775       // 0020466: [CEA] sauv2med : bad conversion
3776       // Provide profile names for a partial field
3777       const SUPPORT* sup = fld->getSupport();
3778       if ( sup && !sup->isOnAllElements() )
3779       {
3780         vector<string> prof_names( sup->getNumberOfTypes() );
3781         for (unsigned itype=0; itype < prof_names.size(); itype++)
3782           prof_names[itype]=STRING( sup->getName())<<"_type"<<sup->getTypes()[itype];
3783         ((SUPPORT*) sup)->setProfilNames( prof_names );
3784       }
3785       _fields->push_back( *it );
3786     }
3787   }
3788   catch (MEDEXCEPTION &ex)
3789   {
3790     INFOS_MED( ex.what() );
3791   }
3792
3793   END_OF_MED(LOC);
3794 }
3795
3796 //================================================================================
3797 /*!
3798  * \brief Return a mesh created while reading fields.
3799  *        Call removeReference() after finishing using it.
3800  */
3801 //================================================================================
3802
3803 MESH* GIBI_MED_RDONLY_DRIVER::getMesh() const
3804 {
3805   if ( _mesh )
3806     _mesh->addReference();
3807   return (MESH*) _mesh;
3808 }
3809
3810
3811 //============================== ====================================================
3812 //============================== FIELD Writting Driver ==============================
3813 //============================== ====================================================
3814
3815 GIBI_MED_WRONLY_DRIVER::GIBI_MED_WRONLY_DRIVER():GIBI_MESH_WRONLY_DRIVER()
3816 {
3817 }
3818 GIBI_MED_WRONLY_DRIVER::GIBI_MED_WRONLY_DRIVER(const string &               fileName,
3819                                                const vector<const FIELD_*>& fields,
3820                                                GMESH *                      ptrMesh)
3821   :GIBI_MESH_DRIVER(fileName,ptrMesh,WRONLY),
3822    GIBI_MESH_WRONLY_DRIVER(fileName,ptrMesh),
3823    _fields( fields )
3824 {
3825   const char * LOC = "GIBI_MED_WRONLY_DRIVER( fileName, vector<FIELD_*>&, MESH *)";
3826   BEGIN_OF_MED(LOC);
3827
3828   if ( !_mesh )
3829     throw MEDEXCEPTION(LOCALIZED(STRING(LOC) << " Bad mesh " << _mesh ));
3830   _fileName = fileName;
3831   _accessMode = WRONLY;
3832 }
3833
3834 GIBI_MED_WRONLY_DRIVER::GIBI_MED_WRONLY_DRIVER(const GIBI_MED_WRONLY_DRIVER & driver):
3835   GIBI_MESH_WRONLY_DRIVER( driver ), _fields( driver._fields )
3836 {
3837 }
3838 GIBI_MED_WRONLY_DRIVER::~GIBI_MED_WRONLY_DRIVER()
3839 {
3840 }
3841 GENDRIVER * GIBI_MED_WRONLY_DRIVER::copy ( void ) const
3842 {
3843   return new GIBI_MED_WRONLY_DRIVER(*this);
3844 }
3845
3846 //=======================================================================
3847 //function : writeDataSection
3848 //purpose  :
3849 //=======================================================================
3850
3851 template< class T, class INTERLACING_TAG>
3852 static void writeDataSection (fstream&                          file,
3853                               const FIELD<T, INTERLACING_TAG> * field,
3854                               const int                         id1,
3855                               const int                         id2) throw (MEDEXCEPTION)
3856 {
3857   const char * LOC="writeDataSection (.....) :";
3858   BEGIN_OF_MED(LOC);
3859
3860   int nbGauss, nbComp = field->getNumberOfComponents();
3861
3862   typedef typename MEDMEM_ArrayInterface<T,INTERLACING_TAG,NoGauss>::Array ArrayNoGauss;
3863   typedef typename MEDMEM_ArrayInterface<T,INTERLACING_TAG,Gauss>::Array   ArrayGauss;
3864
3865   MEDMEM_Array_ * array        = field->getArray();
3866   ArrayNoGauss  * arrayNoGauss = 0;
3867   ArrayGauss    * arrayGauss   = 0;
3868
3869   if ( !array )
3870     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<" Field |"<< field->getName()
3871                                  << "| not allocated"));
3872
3873   if ( array->getGaussPresence() ) {
3874     arrayGauss = field->getArrayGauss();
3875     nbGauss    = arrayGauss->getNbGauss( id1 );
3876   }
3877   else {
3878     arrayNoGauss = field->getArrayNoGauss();
3879     nbGauss      = 1;
3880   }
3881
3882   TFieldCounter fcount( file, 3 ); // 3 values on a line
3883
3884 #ifdef CASTEM_FULL_INTERLACE
3885   const int gauss_step = field->getInterlacingType() == MED_EN::MED_FULL_INTERLACE ? nbComp : 1;
3886 #endif
3887   const bool isNodal = ( field->getSupport()->getEntity() == MED_EN::MED_NODE );
3888
3889   for ( int iComp = 1; iComp <= nbComp; ++iComp )
3890   {
3891     if ( !isNodal )
3892       file << setw(8) << nbGauss       // nb scalar values by element
3893            << setw(8) << ( id2 - id1 ) // total nb of scalar values
3894            << setw(8) << 0
3895            << setw(8) << 0
3896            << endl;
3897
3898     // * 8003   FORMAT(1P,3E22.14)
3899     if ( arrayNoGauss ) {
3900       for (int id = id1; id < id2; id++, fcount++ )
3901         file << setw(22) << arrayNoGauss->getIJ( id, iComp );
3902     }
3903     else {
3904 #ifdef CASTEM_FULL_INTERLACE
3905       for (int id = id1; id < id2; id++ ) {
3906         const T* val = & arrayGauss->getIJK( id, iComp, 1 );
3907         const T* valEnd = val + nbGauss * gauss_step;
3908         for ( ; val < valEnd; val += gauss_step, fcount++ )
3909           file << setw(22) << *val;
3910       }
3911 #else
3912       for ( int iGauss = 1; iGauss <= nbGauss; ++iGauss ) {
3913         for (int id = id1; id < id2; id++, fcount++  )
3914           file << setw(22) << arrayGauss->getIJK( id, iComp, iGauss );
3915       }
3916 #endif
3917     }
3918     fcount.stop();
3919   }
3920   END_OF_MED(LOC);
3921 }
3922
3923 //=======================================================================
3924 //function : write
3925 //purpose  :
3926 //=======================================================================
3927
3928 void GIBI_MED_WRONLY_DRIVER::write( void ) const throw (MEDEXCEPTION)
3929 {
3930   const char* LOC = "void GIBI_MED_WRONLY_DRIVER::write(void) const : ";
3931   BEGIN_OF_MED(LOC);
3932
3933   // we are going to modify the _gibi field
3934   GIBI_MED_WRONLY_DRIVER * me = const_cast<GIBI_MED_WRONLY_DRIVER *>(this);
3935
3936   // get all fields on _mesh and add their support to be written
3937   list<const FIELD_*> fields;
3938   int iField, nbFields = _fields.size();
3939   list<int> nb_sub_list, nb_comp_list;
3940   int nb_nodal_flds = 0;
3941
3942   map<string,int> nameNbMap;
3943   map<string,int> namePrefixMap;
3944   list< string > orderedNames;
3945
3946   list<pair<int,int> >           subIdSizeList; // pair( <submesh id>, <submesh size> );
3947   list<pair<int,int> >::iterator idsize;
3948
3949   // IMP 0020434: mapping GIBI names to MED names
3950   list<nameGIBItoMED> listGIBItoMED_mail;
3951   list<nameGIBItoMED> listGIBItoMED_cham;
3952   list<nameGIBItoMED> listGIBItoMED_comp;
3953
3954   for ( iField = 0; iField < nbFields; ++iField )
3955     {
3956       int nb_sub = 0, nb_comp = 0;
3957       const FIELD_ * f = _fields[ iField ];
3958       if ( f->getValueType() != MED_EN::MED_REEL64 )
3959         {
3960           MESSAGE_MED("GIBI_MED_WRONLY_DRIVER::write( FIELD< int > ) not implemented");
3961           continue;
3962         }
3963       const SUPPORT * sup = f->getSupport();
3964       const medEntityMesh entity = sup->getEntity();
3965
3966       if ( me->addSupport( sup ) )
3967         {
3968           if ( entity == MED_NODE ) fields.push_front( f );
3969           else                      fields.push_back( f );
3970           nb_sub += getSubMeshIdAndSize( sup, subIdSizeList );
3971           nb_comp += nb_sub * f->getNumberOfComponents();
3972         }
3973       if ( nb_sub )
3974         {
3975           if ( entity == MED_NODE )
3976             {
3977               nb_sub_list.push_front ( nb_sub );
3978               orderedNames.push_front( f->getName() );
3979               nb_comp_list.push_front( nb_comp );
3980               nb_nodal_flds++;
3981             }
3982           else
3983             {
3984               nb_sub_list.push_back ( nb_sub );
3985               orderedNames.push_back( f->getName() );
3986               nb_comp_list.push_back( nb_comp );
3987             }
3988         }
3989     }
3990   list< string >::iterator nameIt = orderedNames.begin();
3991   for ( iField = 0 ; nameIt != orderedNames.end(); ++nameIt, ++iField )
3992     {
3993       const bool isNodal = iField < nb_nodal_flds;
3994       int nb_obj = isNodal ? (iField + 1) : (iField - nb_nodal_flds + 1);
3995       addName(nameNbMap, namePrefixMap, *nameIt, nb_obj);
3996
3997       // IMP 0020434: mapping GIBI names to MED names
3998       nameGIBItoMED aMEDName;
3999       aMEDName.gibi_pile = isNodal ? PILE_NODES_FIELD : PILE_FIELD;
4000       aMEDName.gibi_id   = nb_obj;
4001       aMEDName.med_name  = *nameIt;
4002       listGIBItoMED_cham.push_back(aMEDName);
4003     }
4004
4005   // write the mesh
4006
4007   me->writeSupportsAndMesh(listGIBItoMED_mail);
4008
4009   // write fields
4010
4011   if ( !fields.empty() )
4012     {
4013       fstream & gibi = me->_gibi;
4014
4015       TFieldCounter fcount( gibi, 10 );
4016
4017       list<const FIELD_*>::const_iterator itF = fields.begin();
4018       list<int>::iterator itNbSub = nb_sub_list.begin(), itNbComp = nb_comp_list.begin();
4019       int nb_sub = 0, cur_nb_sub = 0, total_nb_comp = 0;
4020       medEntityMesh entity = MED_INVALID;
4021
4022       for ( iField = 0; itF != fields.end(); itF++, iField++ )
4023         {
4024           const FIELD_* f = *itF;
4025
4026           unsigned iComp, nbComp = unsigned( f->getNumberOfComponents() );
4027
4028           // IMP 0020434: mapping GIBI names to MED names
4029           map<string, string> mapMedToGibi;
4030           {
4031             for (int ico = 0; ico < nbComp; ico++)
4032               {
4033                 string compMedName = f->getComponentName(ico + 1);
4034                 compMedName = cleanName(compMedName);
4035                 mapMedToGibi[compMedName] = compMedName;
4036               }
4037             int compIndex = 1;
4038             map<string, string>::iterator namesIt = mapMedToGibi.begin();
4039             for (; namesIt != mapMedToGibi.end(); namesIt++)
4040               {
4041                 string compMedName = (*namesIt).first;
4042                 string compGibiName = compMedName;
4043                 if (compGibiName.size() > 4) {
4044                   // use new name in form "CXXX", where "XXX" is a number
4045                   do
4046                     {
4047                       char strCGN [32];
4048                       strCGN[0] = 'C';
4049                       int pos = 1;
4050                       if (compIndex < 100) strCGN[pos++] = '0';
4051                       if (compIndex < 10 ) strCGN[pos++] = '0';
4052                       sprintf(strCGN + pos, "%d", compIndex++);
4053                       compGibiName = strCGN;
4054                     }
4055                   while (mapMedToGibi.count(compGibiName) > 0); // real component name could be CXXX
4056
4057                   mapMedToGibi[compMedName] = compGibiName;
4058                 }
4059
4060                 compMedName = f->getName() + "." + compMedName;
4061                 nameGIBItoMED aMEDName;
4062                 aMEDName.med_name  = compMedName;
4063                 aMEDName.gibi_pile = PILE_STRINGS;
4064                 aMEDName.gibi_name = compGibiName;
4065                 listGIBItoMED_comp.push_back(aMEDName);
4066               }
4067           } // IMP 0020434
4068
4069           if ( cur_nb_sub == nb_sub && itNbSub != nb_sub_list.end() )
4070             {
4071               // Start writting another field
4072
4073               const medEntityMesh nextEntity = f->getSupport()->getEntity();
4074               if ( nextEntity != entity )
4075                 {
4076                   if ( entity == MED_INVALID || entity == MED_NODE )
4077                     {
4078                       int nb_obj = ( nextEntity == MED_NODE ) ? nb_nodal_flds : orderedNames.size() - nb_nodal_flds;
4079                       gibi << " ENREGISTREMENT DE TYPE   2" << endl;
4080                       gibi << " PILE NUMERO" << ( nextEntity == MED_NODE ? "   2" : "  39" );
4081                       gibi << "NBRE OBJETS NOMMES" << setw(8) << nameNbMap.size();
4082                       gibi << "NBRE OBJETS" << setw(8) << nb_obj << endl;
4083
4084                       me->writeNames( nameNbMap );
4085                     }
4086                   entity = f->getSupport()->getEntity();
4087                 }
4088
4089               total_nb_comp = *(itNbComp++);
4090               nb_sub        = *(itNbSub++);
4091
4092               string description = (*itF)->getDescription();
4093               if ( description.size() > 72 )
4094                 description = description.substr(0,72);
4095
4096               if ( entity == MED_NODE )
4097                 {
4098                   gibi << setw(8) << nb_sub
4099                        << setw(8) << total_nb_comp
4100                        << setw(8) << -1         // IFOUR
4101                        << setw(8) << 0 << endl; // nb attributes
4102                 }
4103               else
4104                 {
4105                   gibi << setw(8) << nb_sub
4106                        << setw(8) << -1
4107                        << setw(8) << 6
4108                        << setw(8) << 72 /*description.size()*/ << endl; // PAL19100
4109                   if ( !description.empty() )
4110                     gibi << setw(72) << description << endl;
4111                   else
4112                     gibi << setw(72) << "Field" << endl;
4113                   gibi << setw(72) << " " << endl;
4114                 }
4115
4116               // Sub Components section
4117
4118               list<const FIELD_*>::const_iterator itF2 = itF;
4119               int vals[9] =
4120                 {
4121                   0, 0, 0, 0, 0, 0, 0, 0, 2
4122                 };
4123               const int nbv = ( entity == MED_NODE ? 3 : 9 );
4124               vector< string > comp_names;
4125               fcount.init(10);
4126               cur_nb_sub = 0;
4127               while ( itF2 != fields.end() && cur_nb_sub < nb_sub )
4128                 {
4129                   const FIELD_* f = *itF2++;
4130                   vals[2] = f->getNumberOfComponents();
4131                   getSubMeshIdAndSize( f->getSupport(), subIdSizeList );
4132                   for ( idsize = subIdSizeList.begin(); idsize != subIdSizeList.end(); idsize++)
4133                     {
4134                       ++cur_nb_sub;
4135
4136                       vals[0] = -idsize->first; // support id
4137                       if ( entity == MED_NODE )
4138                         vals[1] = idsize->second; // nb values
4139                       for ( int i = 0; i < nbv; ++i, fcount++ )
4140                         gibi << setw(8) << vals[ i ];
4141
4142                       for ( int i = 0; i < f->getNumberOfComponents(); ++i )
4143                         comp_names.push_back( f->getComponentName( i+1 ));
4144                     }
4145                 }
4146               fcount.stop();
4147               cur_nb_sub = 0;
4148
4149               if ( entity == MED_NODE )
4150                 {
4151                   // component names
4152                   fcount.init(8);
4153                   gibi << left;
4154                   {
4155                     for ( iComp = 0; iComp < comp_names.size(); ++iComp, fcount++ )
4156                       {
4157                         string compMedName = cleanName(f->getComponentName(iComp + 1));
4158                         string compName = mapMedToGibi[compMedName];
4159                         gibi << " "  << setw(8) << compName;
4160                       }
4161                   }
4162                   gibi << right;
4163                   fcount.stop();
4164
4165                   // nb harmonics
4166                   fcount.init(10);
4167                   for ( int i = 0; i < total_nb_comp; ++i )
4168                     gibi << setw(8) << 0;
4169                   fcount.stop();
4170
4171                   gibi << endl; // TYPE
4172                   gibi << setw(72) << description << endl;
4173                   gibi << endl; // 0 attributes
4174                 }
4175               else
4176                 {
4177                   // dummy strings
4178                   int i_sub;
4179                   for ( fcount.init(4), i_sub = 0; i_sub < nb_sub; ++i_sub, fcount++ )
4180                     gibi << "                  ";
4181                   fcount.stop();
4182
4183                   for ( fcount.init(8), i_sub = 0; i_sub < nb_sub; ++i_sub, fcount++ )
4184                     gibi << "         ";
4185                   fcount.stop();
4186                 }
4187             } // end writing common field data
4188
4189
4190           // loop on sub-components
4191           int id1 = 1;
4192           getSubMeshIdAndSize( f->getSupport(), subIdSizeList );
4193           for ( idsize = subIdSizeList.begin(); idsize != subIdSizeList.end(); idsize++ )
4194             {
4195               cur_nb_sub++;
4196               if ( entity != MED_NODE )
4197                 {
4198                   // component addresses
4199                   fcount.init(10);
4200                   for ( iComp = 0; iComp < nbComp; ++iComp, fcount++ )
4201                     gibi << setw(8) << 777; // a good number
4202                   fcount.stop();
4203                   // component names
4204                   gibi << left;
4205                   fcount.init(8);
4206                   for ( iComp = 0; iComp < nbComp; ++iComp, fcount++ )
4207                     {
4208                       string compMedName = cleanName(f->getComponentName(iComp + 1));
4209                       string compName    = mapMedToGibi[compMedName];
4210                       gibi << " "  << setw(8) << compName;
4211                     }
4212                   fcount.stop();
4213                   // component types
4214                   fcount.init(4);
4215                   for ( iComp = 0; iComp < nbComp; ++iComp, fcount++ )
4216                     gibi << " "  << setw(17) << "REAL*8";
4217                   fcount.stop();
4218                   gibi << right;
4219                 }
4220
4221               // Data section
4222
4223               int id2 = id1 + idsize->second;
4224
4225               if ( f->getInterlacingType() == MED_NO_INTERLACE )
4226                 writeDataSection( gibi, static_cast<const FIELD<double,NoInterlace  > * >(f),
4227                                   id1, id2 );
4228               else if ( f->getInterlacingType() == MED_FULL_INTERLACE )
4229                 writeDataSection( gibi, static_cast<const FIELD<double,FullInterlace> * >(f),
4230                                   id1, id2 );
4231               else
4232                 writeDataSection( gibi, static_cast<const FIELD<double,NoInterlaceByType> * >(f),
4233                                   id1, id2 );
4234
4235               id1 = id2;
4236             }
4237         } // loop on fields
4238     }
4239
4240   // IMP 0020434: mapping GIBI names to MED names
4241   me->writeMEDNames(listGIBItoMED_mail, listGIBItoMED_cham, listGIBItoMED_comp);
4242
4243   me->writeLastRecord();
4244
4245   END_OF_MED(LOC);
4246 }