Back to index

salome-med  6.5.0
MEDMEM_GibiMeshDriver.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 #include <algorithm>
00024 #include <queue>
00025 #include <list>
00026 
00027 #include "MEDMEM_GibiMeshDriver.hxx"
00028 
00029 #ifdef HAS_XDR
00030 // On windows, this file must be included first otherwise
00031 // there is a conflict with the symbol GROUP when compiling the xdr support ...
00032 #include <rpc/xdr.h>
00033 #endif
00034 
00035 #include "MEDMEM_DriversDef.hxx"
00036 
00037 #include "MEDMEM_Family.hxx"
00038 #include "MEDMEM_Field.hxx"
00039 #include "MEDMEM_Group.hxx"
00040 #include "MEDMEM_Coordinate.hxx"
00041 #include "MEDMEM_Connectivity.hxx"
00042 #include "MEDMEM_Mesh.hxx"
00043 #include "MEDMEM_CellModel.hxx"
00044 #include "MEDMEM_define.hxx"
00045 #include "MEDMEM_DriverTools.hxx"
00046 
00047 namespace MEDMEM
00048 {
00049 class FIELD_;
00050 }
00051 
00052 #include <stdio.h>
00053 #include <fcntl.h>
00054 #ifdef WNT
00055 #include <io.h>
00056 #else
00057 #include <unistd.h>
00058 #endif
00059 
00060 #include <float.h>
00061 
00063 using namespace std;
00064 using namespace MED_EN;
00065 using namespace MEDMEM;
00067 
00068 // read or not non-named fields
00069 //#define GIBI_READ_ONLY_NAMED_FIELD
00070 
00071 // to throw an exception when try to write a name longer than 8 or non-unique encounters
00072 //#define THROW_ON_BAD_NAME
00073 
00074 // to see full dump of RESULTATS STRUCTURE INTERMEDIAIRES
00075 #ifdef _DEBUG_
00076 // #undef MESSAGE_MED
00077 // #define MESSAGE_MED(txt) std::cout << txt << endl;
00078 // #undef INFOS_MED
00079 // #define INFOS_MED(txt) std::cout << txt << endl;
00080 #endif
00081 
00082 // Every memory allocation made in the MedDriver members function are desallocated in the Mesh destructor
00083 
00085 //const size_t GIBI_MESH_DRIVER::nb_geometrie_gibi;
00086 
00087 const medGeometryElement GIBI_MESH_DRIVER::geomGIBItoMED[nb_geometrie_gibi] =
00088   {   /*1 */ MED_POINT1 ,/*2 */ MED_SEG2   ,/*3 */ MED_SEG3   ,/*4 */ MED_TRIA3  ,/*5 */ MED_NONE   ,
00089       /*6 */ MED_TRIA6  ,/*7 */ MED_NONE   ,/*8 */ MED_QUAD4  ,/*9 */ MED_NONE   ,/*10*/ MED_QUAD8  ,
00090       /*11*/ MED_NONE   ,/*12*/ MED_NONE   ,/*13*/ MED_NONE   ,/*14*/ MED_HEXA8  ,/*15*/ MED_HEXA20 ,
00091       /*16*/ MED_PENTA6 ,/*17*/ MED_PENTA15,/*18*/ MED_NONE   ,/*19*/ MED_NONE   ,/*20*/ MED_NONE   ,
00092       /*21*/ MED_NONE   ,/*22*/ MED_NONE   ,/*23*/ MED_TETRA4 ,/*24*/ MED_TETRA10,/*25*/ MED_PYRA5  ,
00093       /*26*/ MED_PYRA13 ,/*27*/ MED_NONE   ,/*28*/ MED_NONE   ,/*29*/ MED_NONE   ,/*30*/ MED_NONE   ,
00094       /*31*/ MED_NONE   ,/*32*/ MED_NONE   ,/*33*/ MED_NONE   ,/*34*/ MED_NONE   ,/*35*/ MED_NONE   ,
00095       /*36*/ MED_NONE   ,/*37*/ MED_NONE   ,/*38*/ MED_NONE   ,/*39*/ MED_NONE   ,/*40*/ MED_NONE   ,
00096       /*41*/ MED_NONE   ,/*42*/ MED_NONE   ,/*43*/ MED_NONE   ,/*44*/ MED_NONE   ,/*45*/ MED_NONE   ,
00097       /*46*/ MED_NONE   ,/*47*/ MED_NONE   };
00098 
00099 enum Readable_Piles
00100   {
00101     PILE_SOUS_MAILLAGE=1,
00102     PILE_NODES_FIELD  =2,
00103     PILE_TABLES       =10,
00104     PILE_LREEL        =18,
00105     PILE_LOGIQUES     =24,
00106     PILE_FLOATS       =25,
00107     PILE_INTEGERS     =26,
00108     PILE_STRINGS      =27,
00109     PILE_LMOTS        =29,
00110     PILE_NOEUDS       =32,
00111     PILE_COORDONNEES  =33,
00112     PILE_MODL         =38,
00113     PILE_FIELD        =39,
00114     PILE_LAST_READABLE=39
00115   };
00116 
00117 //=======================================================================
00118 //function : gibi2medGeom
00119 //purpose  :
00120 //=======================================================================
00121 
00122 medGeometryElement GIBI_MESH_DRIVER::gibi2medGeom( size_t gibiTypeNb )
00123 {
00124   if ( gibiTypeNb < 1 || gibiTypeNb > 47 )
00125     return MED_NONE;
00126 
00127   return geomGIBItoMED[ gibiTypeNb - 1 ];
00128 }
00129 
00130 //=======================================================================
00131 //function : med2gibiGeom
00132 //purpose  :
00133 //=======================================================================
00134 
00135 int GIBI_MESH_DRIVER::med2gibiGeom( medGeometryElement medGeomType )
00136 {
00137   for ( int i = 0; i < nb_geometrie_gibi; i++ )
00138     if ( geomGIBItoMED[ i ] == medGeomType )
00139       return i + 1;
00140 
00141   return -1;
00142 }
00143 
00144 //=======================================================================
00145 //function : getGroupId
00146 //purpose  :
00147 //=======================================================================
00148 
00149 static int getGroupId(const vector<int>& support_ids, _intermediateMED*  medi)
00150 {
00151   int group_id = 0;
00152   vector<int>::const_iterator sb = support_ids.begin(), se = support_ids.end();
00153   if (support_ids.size() == 1 || // one or equal support ids
00154       *std::max_element( sb, se ) == *std::min_element( sb, se ))
00155   {
00156     group_id = support_ids[0] - 1;
00157   }
00158   else
00159   {
00160     // try to find an existing group with the same sub-groups
00161     set<int> sup_set;
00162     sup_set.insert( sb, se );
00163 
00164     for ( group_id = 0; group_id < (int)medi->groupes.size(); ++group_id )
00165     {
00166       if (sup_set.size() == medi->groupes[ group_id ].groupes.size() &&
00167           std::equal (sup_set.begin(), sup_set.end(),
00168                       medi->groupes[ group_id ].groupes.begin()))
00169         break;
00170     }
00171     if ( group_id == (int)medi->groupes.size() )
00172     {
00173       // no such a group, add a new one
00174       medi->groupes.push_back( _groupe() );
00175       _groupe& new_grp = medi->groupes.back();
00176       new_grp.groupes.reserve( sup_set.size() );
00177       for ( set<int>::iterator it = sup_set.begin(); it != sup_set.end(); it++ ) {
00178         new_grp.groupes.push_back( *it );
00179       }
00180     }
00181   }
00182   return group_id;
00183 }
00184 
00185 //=======================================================================
00186 //function : isNamedObject
00187 //purpose  :
00188 //=======================================================================
00189 
00190 //#ifdef GIBI_READ_ONLY_NAMED_FIELD
00191 static inline bool isNamedObject( int obj_index, const vector<int>& indices_objets_nommes )
00192 {
00193   return ( std::find( indices_objets_nommes.begin(), indices_objets_nommes.end(), obj_index)
00194            != indices_objets_nommes.end() );
00195 }
00196 //#endif
00197 
00198 //=======================================================================
00199 //function : setFieldNames
00200 //purpose  : set field names
00201 //=======================================================================
00202 
00203 static void setFieldNames(const vector< _fieldBase* >& fields,
00204                           const vector<string>&        objets_nommes,
00205                           const vector<int>&           indices_objets_nommes)
00206 {
00207   // set field names
00208   unsigned i;
00209   set<string> fnames;
00210   for ( i = 0; i < indices_objets_nommes.size(); ++i ) {
00211     int fieldIndex = indices_objets_nommes[ i ];
00212     fnames.insert( objets_nommes[ i ]);
00213     if ( fields[ fieldIndex - 1 ] )
00214       fields[ fieldIndex - 1 ]->_name = objets_nommes[ i ];
00215   }
00216   int noNameIndex = 0;
00217   for ( i = 0; i < fields.size(); ++i ) {
00218     if ( !fields[ i ] ) {
00219       if ( !isNamedObject( i+1, indices_objets_nommes ))
00220         ++noNameIndex;
00221     }
00222     else if ( fields[ i ]->_name.empty() ) {
00223       do {
00224         fields[ i ]->_name = STRING("F_") << ++noNameIndex;
00225       } while ( !fnames.insert( fields[ i ]->_name ).second );
00226     }
00227   }
00228 }
00229 
00230 //=======================================================================
00231 //function : read
00232 //purpose  :
00233 //=======================================================================
00234 
00235 #define GIBI_EQUAL(var_str, stat_str) \
00236   (strncmp (var_str, stat_str, strlen(stat_str)) == 0)
00237 #define DUMP_LINE_NB " on line " << _lineNb
00238 
00239 bool GIBI_MESH_RDONLY_DRIVER::readFile (_intermediateMED* medi, bool readFields )
00240 {
00241   const char* LOC = "GIBI_MESH_RDONLY_DRIVER::readFile() : ";
00242   BEGIN_OF_MED(LOC);
00243 
00244   // LECTURE DES DONNEES DS FICHIER GIBI
00245 
00246   Readable_Piles readable_Piles [] = {
00247     PILE_SOUS_MAILLAGE,
00248     PILE_NODES_FIELD,
00249     PILE_TABLES,
00250     PILE_LREEL,
00251     PILE_LOGIQUES,
00252     PILE_FLOATS,
00253     PILE_INTEGERS,
00254     PILE_STRINGS,
00255     PILE_LMOTS,
00256     PILE_NOEUDS,
00257     PILE_COORDONNEES,
00258     PILE_MODL,
00259     PILE_FIELD,
00260     PILE_LAST_READABLE
00261   };
00262   // other known piles:
00263   // PILE NUMERO  26 - Integers
00264   // PILE NUMERO  25 - Floats
00265 
00266   char* ligne; // pour lire une ligne
00267   const char* enregistrement_type=" ENREGISTREMENT DE TYPE";
00268   vector<int> numero_noeuds; // tableau de travail (indices)
00269   set<int> donePiles; // already read piles
00270   unsigned space_dimension = 0;
00271 
00272   // IMP 0020434: mapping GIBI names to MED names
00273   list<nameGIBItoMED> listGIBItoMED_mail; // to be read from PILE_TABLES, from table "MED_MAIL"
00274   list<nameGIBItoMED> listGIBItoMED_cham; // to be read from PILE_TABLES, from table "MED_CHAM"
00275   list<nameGIBItoMED> listGIBItoMED_comp; // to be read from PILE_TABLES, from table "MED_COMP"
00276   map<int,string> mapStrings; // to be read from PILE_STRINGS
00277   vector<_fieldBase*> node_fields;
00278   vector<_fieldBase*> cell_fields;
00279 
00280 #ifdef HAS_XDR
00281   if ( _is_xdr)
00282     {
00283       _curPos = 0;
00284       _iRead = 0;
00285       _nbToRead = 0;
00286     }
00287 #endif
00288 
00289   while ( getNextLine(ligne, false)) // boucle externe de recherche de "ENREGISTREMENT DE TYPE"
00290   {
00291 #ifdef HAS_XDR
00292     if ( !_is_xdr)
00293 #endif
00294       if ( !GIBI_EQUAL( ligne, enregistrement_type ))
00295         continue; // "ENREGISTREMENT DE TYPE" non trouvé -> on lit la ligne suivante
00296 
00297     // lecture du numéro d'enregistrement
00298     int numero_enregistrement;
00299 #ifdef HAS_XDR
00300     if(_is_xdr)
00301       numero_enregistrement = getInt();
00302     else
00303 #endif
00304       numero_enregistrement = atoi( ligne + strlen(enregistrement_type) + 1 );
00305 
00306     enum { ENREG_TYPE_2=2, ENREG_TYPE_4=4}; // énumération des types d'enregistrement traités
00307 #ifdef HAS_XDR
00308     enum { ENREG_TYPE_5=5, ENREG_TYPE_7=7}; // (only for xdr)
00309 #endif
00310     int numero_pile, nb_objets_nommes, nb_objets, nb_indices;
00311     vector<int> indices_objets_nommes;
00312     vector<string> objets_nommes;
00313 
00314     if (numero_enregistrement == ENREG_TYPE_4)
00315     {
00316 #ifdef HAS_XDR
00317       if(_is_xdr)
00318         {
00319           getInt(); // skip NIVEAU
00320           getInt(); // skip ERREUR
00321           space_dimension = getInt();
00322           getFloat(); // skip DENSITE
00323         }
00324       else
00325         {
00326 #endif
00327           getNextLine(ligne);
00328           const char* s = " NIVEAU  15 NIVEAU ERREUR   0 DIMENSION";
00329           space_dimension = atoi( ligne + strlen( s ) + 1 );
00330           if ( !GIBI_EQUAL( ligne, " NIVEAU" ) || space_dimension < 1 ) {
00331             INFOS_MED( " Could not read file: syntax error in type 4 record" << DUMP_LINE_NB );
00332             return false;
00333           }
00334 #ifdef HAS_XDR
00335         }
00336 #endif
00337     }
00338 #ifdef HAS_XDR
00339     else if (numero_enregistrement == ENREG_TYPE_7)
00340     {
00341       if(_is_xdr)
00342         {
00343           getInt(); // skip NOMBRE INFO CASTEM2000
00344           getInt(); // skip IFOUR
00345           getInt(); // skip NIFOUR
00346           getInt(); // skip IFOMOD
00347           getInt(); // skip IECHO
00348           getInt(); // skip IIMPI
00349           getInt(); // skip IOSPI
00350           getInt(); // skip ISOTYP
00351           getInt(); // skip NSDPGE
00352         }
00353     }
00354 #endif
00355     else if (numero_enregistrement == ENREG_TYPE_2 )
00356     {
00357       if ( space_dimension == 0 ) {
00358         INFOS_MED( "Missing ENREGISTREMENT DE TYPE   4" << DUMP_LINE_NB );
00359         return false;
00360       }
00361       // FORMAT(' PILE NUMERO',I4,'NBRE OBJETS NOMMES',I8,'NBRE OBJETS',I8)
00362       getNextLine(ligne);
00363 #ifdef HAS_XDR
00364       if(_is_xdr)
00365         {
00366           initIntReading(3);
00367           numero_pile = getInt(); next();
00368           nb_objets_nommes = getInt(); next();
00369           nb_objets = getInt(); next();
00370         }
00371       else
00372         {
00373 #endif
00374           const char *s1 = " PILE NUMERO", *s2 = "NBRE OBJETS NOMMES", *s3 = "NBRE OBJETS";
00375           if ( ! GIBI_EQUAL( ligne, s1 ) ) {
00376             INFOS_MED( " Could not read file: error in type 2 record. " << ligne << DUMP_LINE_NB );
00377             return false;
00378           }
00379           ligne = ligne + strlen(s1);
00380           numero_pile = atoi( ligne );
00381           ligne = ligne + 4 + strlen(s2);
00382           nb_objets_nommes = atoi( ligne );
00383           ligne = ligne + 8 + strlen(s3);
00384           nb_objets = atoi( ligne );
00385 #ifdef HAS_XDR
00386         }
00387 #endif
00388       if ( nb_objets_nommes<0 || nb_objets<0  ) {
00389         INFOS_MED(" Could not read file: " << nb_objets << " " <<nb_objets_nommes << DUMP_LINE_NB );
00390         return false;
00391       }
00392       if ( !donePiles.insert( numero_pile ).second ) // piles may repeat
00393         continue;
00394 
00395       if ( numero_pile > PILE_LAST_READABLE )
00396         break; // stop file reading
00397 
00398       // skip not readable piles
00399       int i = -1;
00400       while ( readable_Piles[ ++i ] != PILE_LAST_READABLE )
00401         if ( readable_Piles[ i ] == numero_pile )
00402           break;
00403       if ( readable_Piles[ i ] != numero_pile )
00404 #ifdef HAS_XDR
00405         {
00406           if(_is_xdr)
00407             { 
00408               cout << "XDR : NUMERO PILE " << numero_pile << " not implemented !!!" << endl ;
00409               throw MEDEXCEPTION("XDR : NUMERO PILE not implemented !!!");
00410             }
00411 #endif
00412           continue;
00413 #ifdef HAS_XDR
00414         }
00415 #endif
00416 
00417       // lecture des objets nommés et de leurs indices
00418       objets_nommes.resize(nb_objets_nommes);
00419       indices_objets_nommes.resize(nb_objets_nommes);
00420       //indices_objets_nommes.resize(nb_objets);
00421       for ( initNameReading( nb_objets_nommes ); more(); next() ) {
00422         objets_nommes[ index() ] = getName();
00423       }
00424       for ( initIntReading( nb_objets_nommes ); more(); next() )
00425       //for ( initIntReading( nb_objets ); more(); next() )
00426         indices_objets_nommes[ index() ] = getInt();
00427 
00428       // boucle interne : lecture de la pile
00429 
00430       MESSAGE_MED(PREFIX_MED << "---- Traitement pile " << numero_pile);
00431 
00432       // -----------------------------------
00433       //                        MESH GROUPS
00434       // -----------------------------------
00435 
00436       if (numero_pile == PILE_SOUS_MAILLAGE ) // PILE NUMERO   1
00437       {
00438         map<int,int> strangeGroupType;
00439         medi->groupes.reserve(nb_objets*2); // fields may add some groups
00440         map< int , int > nbElemsByGeomType;
00441 
00442         for (int objet=0; objet!=nb_objets; ++objet) // pour chaque groupe
00443         {
00444           initIntReading( 5 );
00445           unsigned type_geom_castem = getInt(); next();
00446           unsigned nb_sous_maillage = getInt(); next();
00447           unsigned nb_reference     = getInt(); next();
00448           unsigned nb_noeud         = getInt(); next();
00449           unsigned nb_elements      = getInt();
00450 #ifdef HAS_XDR
00451           if(_is_xdr) next();
00452 #endif
00453 
00454           // le cas type_geom_castem=0 correspond aux maillages composites
00455           if (type_geom_castem<0) {
00456             INFOS_MED(" Error while reading file, bad geometric type:" <<
00457                   type_geom_castem << DUMP_LINE_NB );
00458             return false;
00459           }
00460 
00461           medi->groupes.push_back(_groupe());
00462           _groupe & groupe = medi->groupes.back();
00463 
00464           // Issue 0021311. Allocate places for names of referring groups
00465           // that will be possibly filled after reading long names from
00466           // PILE_TABLES and PILE_STRINGS
00467           groupe.refNames.resize( nb_reference );
00468 
00469           // si le groupe se compose de sous-maillages (ie groupe composite)
00470           if (type_geom_castem==0 && nb_sous_maillage>0)
00471           {
00472             // lecture des indices des sous-maillages, stockage.
00473             // les mailles correspondant a ces sous_maillages seront inserees a la fin du case
00474             groupe.groupes.resize( nb_sous_maillage );
00475             for ( initIntReading( nb_sous_maillage ); more(); next() ) {
00476               groupe.groupes[ index() ] = getInt();
00477             }
00478             if ( readFields )
00479               std::sort( groupe.groupes.begin(), groupe.groupes.end() );
00480           }
00481           // lecture des references (non utilisé pour MED)
00482           for ( i = 0; i < (int)nb_reference; i += 10 ) {// FORMAT(10I8)
00483             getNextLine(ligne);
00484           }
00485 #ifdef HAS_XDR
00486           if(_is_xdr)
00487             {
00488               for (initIntReading(nb_reference); more(); next());
00489             }
00490 #endif
00491           // lecture des couleurs (non utilisé pour MED)
00492           for ( i = 0; i < (int)nb_elements; i += 10 ) {
00493             getNextLine(ligne);
00494           }
00495 #ifdef HAS_XDR
00496           if(_is_xdr)
00497             {
00498               for (initIntReading(nb_elements); more(); next());
00499             }
00500 #endif
00501           // not a composit group
00502           if (type_geom_castem>0 && nb_sous_maillage==0)
00503           {
00504             medGeometryElement medType = gibi2medGeom(type_geom_castem);
00505 
00506             initIntReading( nb_elements * nb_noeud );
00507             if ( medType == MED_NONE ) { // look for group end
00508               while ( more() )
00509                 next();
00510               strangeGroupType.insert( make_pair( objet, type_geom_castem ));
00511               continue;
00512             }
00513             if ( medType == MED_POINT1 )
00514               medType = MED_NONE; // issue 21199
00515             if ( nbElemsByGeomType.find( medType ) == nbElemsByGeomType.end())
00516               nbElemsByGeomType[ medType ] = 0;
00517             int & order = nbElemsByGeomType[ medType ];
00518 
00519             pair<set<_maille>::iterator,bool> p;
00520             pair<map<int,_noeud>::iterator,bool> p_no;
00521             _noeud no;
00522             no.coord.resize(space_dimension);
00523             _maille ma( medType, nb_noeud );
00524             ma.sommets.resize(nb_noeud);
00525             groupe.mailles.resize( nb_elements );
00526 
00527             // lecture pour chaque maille des sommets et insertions
00528             for ( i = 0; i < int(nb_elements); ++i )
00529             {
00530               for (unsigned n = 0; n < nb_noeud; ++n, next() )
00531               {
00532                 if ( !more() ) {
00533                   INFOS_MED( " Error while reading elem nodes ");
00534                   return false;
00535                 }
00536                 no.number = getInt();
00537                 p_no=medi->points.insert(make_pair(no.number, no));
00538                 ma.sommets[n]=p_no.first;
00539               }
00540               ma.setOrdre( ++order );
00541               // on stocke dans le groupe un iterateur sur la maille
00542               groupe.mailles[i] = medi->insert(ma);
00543             }
00544           }
00545         } // loop on groups
00546 
00547         // set group names
00548         for (i=0; i!=nb_objets_nommes; ++i) {
00549           int grpID = indices_objets_nommes[i];
00550           _groupe & grp = medi->groupes[ grpID-1 ];
00551           if ( !grp.nom.empty() ) // a group has several names
00552           { // create a group with subgroup grp and named grp.nom
00553             medi->groupes.push_back(_groupe());
00554             medi->groupes.back().groupes.push_back( grpID );
00555             medi->groupes.back().nom = grp.nom;
00556           }
00557           grp.nom=objets_nommes[i];
00558           map<int,int>::iterator it = strangeGroupType.find( grpID - 1 );
00559           if ( it != strangeGroupType.end() ) {
00560 #ifdef _DEBUG
00561             cout << "Skip " << grp.nom << " of not supported CASTEM type: " << it->second << endl;
00562 #endif
00563             //INFOS_MED( "Skip " << grp.nom << " of not supported CASTEM type: " << it->second );
00564           }
00565         }
00566 
00567       }// Fin case PILE_SOUS_MAILLAGE
00568 
00569 #ifdef HAS_XDR
00570 
00571       // ---------------------------------
00572       // ---------------------------------
00573       
00574       else if ( numero_pile == PILE_LREEL ) // PILE NUMERO  18
00575         {
00576           if(_is_xdr)
00577             {
00578               for (int objet=0; objet!=nb_objets; ++objet) // pour chaque groupe
00579                 {
00580                   initIntReading(1);
00581                   int nb_vals = getInt();
00582                   next();
00583                   initDoubleReading(nb_vals);
00584                   for(i=0; i<nb_vals; i++) next();
00585                 }
00586             }
00587         } // Fin case pile 18
00588       
00589       // ---------------------------------
00590       // ---------------------------------
00591       
00592       else if ( numero_pile == PILE_LOGIQUES ) // PILE NUMERO  24
00593         {
00594           if(_is_xdr)
00595             {
00596               initIntReading(1);
00597               int nb_vals = getInt();
00598               next();
00599               initIntReading(nb_vals);
00600               for(i=0; i<nb_vals; i++) next();
00601             }
00602         } // Fin case pile 24
00603       
00604       // ---------------------------------
00605       // ---------------------------------
00606       
00607       else if ( numero_pile == PILE_FLOATS ) // PILE NUMERO  25
00608         {
00609           if(_is_xdr)
00610             {
00611               initIntReading(1);
00612               int nb_vals = getInt();
00613               next();
00614               initDoubleReading(nb_vals);
00615               for(i=0; i<nb_vals; i++) next();
00616             }
00617         } // Fin case pile 25
00618       
00619       // ---------------------------------
00620       // ---------------------------------
00621       
00622       else if ( numero_pile == PILE_INTEGERS ) // PILE NUMERO  26
00623         {
00624           if(_is_xdr)
00625             {
00626               initIntReading(1);
00627               int nb_vals = getInt();
00628               next();
00629               initIntReading(nb_vals);
00630               for(i=0; i<nb_vals; i++) next();
00631             }
00632         } // Fin case pile 26
00633       
00634       // ---------------------------------
00635       // ---------------------------------
00636       
00637       else if ( numero_pile == PILE_LMOTS ) // PILE NUMERO  29
00638         {
00639           if(_is_xdr)
00640             {
00641               for (int objet=0; objet!=nb_objets; ++objet) // pour chaque groupe
00642                 {
00643                   initIntReading(2);
00644                   int len = getInt();
00645                   next();
00646                   int nb_vals = getInt();
00647                   next();
00648                   int nb_char = len*nb_vals;
00649                   int nb_char_tmp = 0;
00650                   int fixed_length = 71;
00651                   while (nb_char_tmp < nb_char)
00652                     {
00653                       int remain_len = nb_char - nb_char_tmp;
00654                       int width;
00655                       if ( remain_len > fixed_length )
00656                         {
00657                           width = fixed_length;
00658                         }
00659                       else
00660                         {
00661                           width = remain_len;
00662                         }
00663                       initNameReading(1, width);
00664                       next();
00665                       nb_char_tmp += width;
00666                     }
00667                 }
00668             }
00669         } // Fin case pile 29
00670       
00671       // ---------------------------------
00672       // ---------------------------------
00673       
00674       else if ( numero_pile == PILE_MODL ) // PILE NUMERO  38
00675         {
00676           if(_is_xdr)
00677             {
00678               for (int objet=0; objet!=nb_objets; ++objet) // pour chaque groupe
00679                 {
00680                   // see wrmodl.eso
00681                   initIntReading(10);
00682                   int n1  = getInt() ; next();
00683                   int nm2 = getInt() ; next();
00684                   int nm3 = getInt() ; next();
00685                   int nm4 = getInt() ; next();
00686                   int nm5 = getInt() ; next();
00687                   int n45 = getInt() ; next();
00688                   /*int nm6 =*/ getInt() ; next();
00689                   /*int nm7 =*/ getInt() ; next();
00690                   next();
00691                   next();
00692                   int nm1 = n1 * n45;
00693                   int nm9 = n1 * 16;
00694                   for (initIntReading(nm1); more(); next());
00695                   for (initIntReading(nm9); more(); next());
00696                   for (initNameReading(nm5, 8); more(); next());
00697                   for (initNameReading(nm2, 8); more(); next());
00698                   for (initNameReading(nm3, 8); more(); next());
00699                   for (initIntReading(nm4); more(); next());
00700                 }
00701             }
00702         } // Fin case pile 38
00703 
00704 #endif  // HAS_XDR
00705       
00706       // ---------------------------------
00707       //                            NODES
00708       // ---------------------------------
00709 
00710       else if ( numero_pile == PILE_NOEUDS ) // PILE NUMERO  32
00711       {
00712         getNextLine( ligne );
00713         std::vector<int> place_noeuds;
00714 #ifdef HAS_XDR
00715         if(_is_xdr) 
00716           {
00717             initIntReading(1);
00718             nb_indices = getInt();
00719             next();
00720           }
00721         else
00722 #endif
00723           nb_indices = atoi ( ligne );
00724         if (nb_indices != nb_objets)
00725         {
00726           INFOS_MED("Erreur de lecture dans enregistrement de pile " <<
00727                 PILE_NOEUDS << DUMP_LINE_NB );
00728           return false;
00729         }
00730 
00731         place_noeuds.resize(nb_objets);
00732         for ( initIntReading( nb_objets ); more(); next() )
00733           place_noeuds[ index() ] = getInt();
00734         int max=(* std::max_element(place_noeuds.begin(),place_noeuds.end()));
00735 
00736         // numero_noeuds contient pour chacun des max noeuds qu'on va lire dans le case PILE_COORDONNEES
00737         // son indice dans la connectivite du maillage. Cet indice correspond egalement a la cle du map
00738         // medi->points ou l'on stocke les noeuds.
00739         numero_noeuds.resize(max,-1);
00740         for (unsigned i=0; i!=place_noeuds.size(); ++i)
00741           numero_noeuds[place_noeuds[i]-1]=i+1;
00742       }
00743 
00744       // ---------------------------------------
00745       //                            COORDINATES
00746       // ---------------------------------------
00747 
00748       else if ( numero_pile == PILE_COORDONNEES )// PILE NUMERO  33
00749       {
00750         getNextLine( ligne );
00751         unsigned nb_reels;
00752 #ifdef HAS_XDR
00753         if(_is_xdr) 
00754           {
00755             initIntReading(1);
00756             nb_reels = getInt();
00757             next();
00758           }
00759         else
00760 #endif
00761           nb_reels = atoi( ligne );
00762         // PROVISOIRE : certains fichier gibi n`ont
00763         if (nb_reels < numero_noeuds.size()*(space_dimension)) {
00764           INFOS_MED("Erreur de lecture dans enregistrement de pile " <<
00765                 PILE_COORDONNEES << DUMP_LINE_NB );
00766           return false;
00767         }
00768         initDoubleReading( nb_reels );
00769         map< int, _noeud >::iterator pIt;
00770         for (unsigned i=0; i!=numero_noeuds.size(); ++i)
00771         {
00772           // si le noeud est utilisé dans le maillage,
00773           //on lit ses coordonnées et on les stocke dans la structure
00774           if (( numero_noeuds[i] != -1 ) &&
00775               (( pIt = medi->points.find(numero_noeuds[i])) != medi->points.end()))
00776           {
00777             for (unsigned j=0; j!=space_dimension; ++j, next())
00778               pIt->second.coord[j] = getDouble();
00779 #ifdef HAS_XDR
00780             if(_is_xdr) getDouble(); // skip density
00781 #endif
00782             next(); // on ne conserve pas la densite
00783           }
00784           else // sinon, on passe au noeud suivant
00785           {
00786             for (unsigned j=0; j!=space_dimension+1; ++j)
00787 #ifdef HAS_XDR
00788               {
00789                 if(_is_xdr) getDouble(); // skip ...
00790 #endif
00791                 next();
00792 #ifdef HAS_XDR
00793               }
00794 #endif
00795           }
00796         }
00797 #ifdef HAS_XDR
00798         if(_is_xdr)
00799           {
00800             for(unsigned i=0; i!=nb_reels-numero_noeuds.size()*(space_dimension+1); ++i)
00801               {
00802                 next(); // skip ...
00803               }
00804           }
00805 #endif
00806       }
00807 
00808       // ---------------------------------------
00809       //                            NODE FIELDS
00810       // ---------------------------------------
00811 
00812       else if ( numero_pile == PILE_NODES_FIELD && readFields ) // PILE NUMERO   2
00813       {
00814         //vector< _fieldBase* > fields( nb_objets );
00815         node_fields.resize(nb_objets, (_fieldBase*)0);
00816         for (int objet=0; objet!=nb_objets; ++objet) // pour chaque field
00817         {
00818           bool ignoreField = false;
00819 #ifdef GIBI_READ_ONLY_NAMED_FIELD
00820           ignoreField = !isNamedObject( objet+1, indices_objets_nommes );
00821           if ( ignoreField )
00822             INFOS_MED("Skip non-named field " << objet+1 << DUMP_LINE_NB);
00823 #endif
00824 
00825           // EXAMPLE ( with no values )
00826 
00827           // (1)       4       7       2       1
00828           // (2)     -88       0       3     -89       0       1     -90       0       2     -91
00829           // (2)       0       1
00830           // (3) FX   FY   FZ   FZ   FX   FY   FLX
00831           // (4)       0       0       0       0       0       0       0
00832           // (5)           cree  par  muc pri
00833           // (6)
00834           // (7)       2
00835 
00836           // (1): nb subcomponents, nb components(total), IFOUR, nb attributes
00837           initIntReading( 4 );
00838           int i_sub, nb_sub         = getInt(); next();
00839           int i_comp, total_nb_comp = getInt(); next();
00840           next(); // ignore IFOUR
00841           int nb_attr = getInt();
00842 #ifdef HAS_XDR
00843           if(_is_xdr) next();
00844 #endif
00845           if ( nb_sub < 0 || total_nb_comp < 0 || nb_attr < 0 ) {
00846             INFOS_MED("Error of field reading: wrong nb of components "
00847                   << nb_sub << " " << total_nb_comp << DUMP_LINE_NB);
00848             return false;
00849           }
00850           // (2) loop on subcomponents of a field, for each read
00851           // (a) support, (b) number of values and (c) number of components
00852           vector<int>     support_ids( nb_sub );
00853           vector<int>     nb_values  ( nb_sub );
00854           vector<int>     nb_comps   ( nb_sub );
00855           int total_nb_values = 0;
00856           initIntReading( nb_sub * 3 );
00857           for ( i_sub = 0; i_sub < nb_sub; ++i_sub )
00858           {
00859             support_ids[ i_sub ] = -getInt(); next(); // (a) reference to support
00860             if ( support_ids[ i_sub ] < 1 || support_ids[ i_sub ] > (int)medi->groupes.size() ) {
00861               INFOS_MED("Error of field reading: wrong mesh reference "<<
00862                     support_ids[ i_sub ] << DUMP_LINE_NB );
00863               return false;
00864             }
00865             nb_values[ i_sub ] = getInt(); next();    // (b) nb points
00866             total_nb_values += nb_values[ i_sub ];
00867             if ( nb_values[ i_sub ] < 0 ) {
00868               INFOS_MED(" Wrong nb of points: " << nb_values[ i_sub ]  << DUMP_LINE_NB );
00869               return false;
00870             }
00871             nb_comps[ i_sub ] = getInt(); next();     // (c) nb of components in i_sub
00872           }
00873           // create a field if there are values
00874           _field<double>* fdouble = 0;
00875           if ( total_nb_values > 0 && !ignoreField )
00876           {
00877             fdouble = new _field<double>( MED_REEL64, nb_sub, total_nb_comp );
00878             medi->fields.push_back( node_fields[ objet ] = fdouble );
00879           }
00880           // (3) component names
00881           initNameReading( total_nb_comp, 4 );
00882           for ( i_sub = 0; i_sub < nb_sub; ++i_sub )
00883           {
00884             // store support id and nb components of a sub
00885             if ( fdouble )
00886               fdouble->_sub[ i_sub ].setData( nb_comps[ i_sub ], support_ids[ i_sub ] );
00887             for ( i_comp = 0; i_comp < nb_comps[ i_sub ]; ++i_comp, next() )
00888             {
00889               ASSERT_MED( more() );
00890               // store component name
00891               if ( fdouble )
00892                 fdouble->_sub[ i_sub ].compName( i_comp ) = getName();
00893             }
00894           }
00895           // (4) nb harmonics ( ignored )
00896           for ( initIntReading( total_nb_comp ); more(); next() )
00897             ;
00898           // (5) TYPE ( ignored )
00899           getNextLine( ligne );
00900 #ifdef HAS_XDR
00901           if(_is_xdr) for (initNameReading(1, 71); more(); next());
00902 #endif
00903           // (6) TITRE ( ignored )
00904           getNextLine( ligne );
00905 #ifdef HAS_XDR
00906           if(_is_xdr) for (initNameReading(1, 71); more(); next());
00907 #endif
00908           // (7) attributes ( ignored )
00909           for ( initIntReading( nb_attr ); more(); next() )
00910             ;
00911 
00912           for ( i_sub = 0; i_sub < nb_sub; ++i_sub )
00913           {
00914             // loop on components: read values
00915             initDoubleReading( nb_values[ i_sub ] * nb_comps[ i_sub ] );
00916             for ( i_comp = 0; i_comp < nb_comps[ i_sub ]; ++i_comp )
00917             {
00918               vector<double>* vals = 0;
00919               if ( fdouble ) vals = & fdouble->addComponent( nb_values[ i_sub ] );
00920               for ( int i = 0; more() && i < nb_values[ i_sub ]; next(), ++i ) {
00921                 if ( vals ) (*vals)[ i ] = getDouble();
00922               }
00923             }
00924           } // loop on subcomponents of a field
00925 
00926           // set id of a group including all subs supports but only
00927           // if all subs have the same components
00928           if ( fdouble && fdouble->hasSameComponentsBySupport() )
00929             fdouble->_group_id = getGroupId( support_ids, medi );
00930 
00931         } // end loop on field objects
00932 
00933         // set field names
00934         setFieldNames( node_fields, objets_nommes, indices_objets_nommes );
00935 
00936       }  // Fin numero_pile == PILE_NODES_FIELD
00937 
00938       // -------------------------------------------------
00939       //                                           FIELDS
00940       // -------------------------------------------------
00941 
00942       else if ( numero_pile == PILE_FIELD && readFields ) // PILE NUMERO  39
00943       {
00944         // REAL EXAMPLE
00945 
00946         // (1)        1       2       6      16
00947         // (2)                                                         CARACTERISTIQUES
00948         // (3)      -15  317773       4       0       0       0      -2       0       3
00949         // (4)             317581
00950         // (5)  0
00951         // (6)   317767  317761  317755  317815
00952         // (7)  YOUN     NU       H        SIGY
00953         // (8)  REAL*8            REAL*8            REAL*8            REAL*8
00954         // (9)        1       1       0       0
00955         // (10)  2.00000000000000E+05
00956         // (11)       1       1       0       0
00957         // (12)  3.30000000000000E-01
00958         // (13)       1       1       0       0
00959         // (14)  1.00000000000000E+04
00960         // (15)       6     706       0       0
00961         // (16)  1.00000000000000E+02  1.00000000000000E+02  1.00000000000000E+02
00962         // (17)  1.00000000000000E+02  1.00000000000000E+02  1.00000000000000E+02
00963         // (18)  ...
00964 
00965         //vector< _fieldBase* > fields( nb_objets, (_fieldBase*)0 );
00966         cell_fields.resize(nb_objets, (_fieldBase*)0);
00967         for (int objet=0; objet!=nb_objets; ++objet) // pour chaque field
00968         {
00969           bool ignoreField = false;
00970 #ifdef GIBI_READ_ONLY_NAMED_FIELD
00971           ignoreField = !isNamedObject( objet+1, indices_objets_nommes );
00972           if ( ignoreField )
00973             INFOS_MED("Skip non-named field " << objet+1 << DUMP_LINE_NB);
00974 #endif
00975           initIntReading( 4 );
00976           int i_sub, nb_sub = getInt(); // (1) <nb_sub> 2 6 <title length>
00977           if ( nb_sub < 1 ) {
00978             INFOS_MED("Error of field reading: wrong nb of subcomponents " <<
00979                   nb_sub << DUMP_LINE_NB );
00980             return false;
00981           }
00982           next(); next(); next(); // skip (1) <nb_sub> 2 6
00983           int title_length = getInt(); // <title length>
00984 #ifdef HAS_XDR
00985           if(_is_xdr) next();
00986 #endif
00987           string description;
00988           if ( title_length ) {
00989 #ifdef HAS_XDR
00990             if(_is_xdr)
00991               {
00992                 initNameReading(1, title_length);
00993                 description = getName();
00994                 next();
00995               }
00996             else
00997               {
00998 #endif
00999                 getNextLine( ligne ); // (2) title
01000                 const int len = 72; // line length
01001                 // title is right justified
01002                 description = string(ligne + len - title_length, title_length);
01003               }
01004 #ifdef HAS_XDR
01005           }
01006 #endif
01007           // look for a line starting with '-' : <reference to support>
01008 #ifdef HAS_XDR
01009           if(_is_xdr)
01010             {
01011               initIntReading( nb_sub * 9 );
01012             }
01013           else
01014             {
01015 #endif
01016               do {
01017                 initIntReading( nb_sub * 9 );
01018               } while ( getInt() >= 0 );
01019 #ifdef HAS_XDR
01020             }
01021 #endif
01022           int total_nb_comp = 0;
01023           vector<int> support_ids( nb_sub ), nb_comp( nb_sub );
01024           for ( i_sub = 0; i_sub < nb_sub; ++i_sub )
01025           {                                           // (3)
01026             support_ids[ i_sub ] = -getInt(); next(); // <reference to support>
01027             next();                                   // ignore <address>
01028             nb_comp    [ i_sub ] =  getInt(); next(); // <nb of components in the sub>
01029             for ( i = 0; i < 6; ++i )                 // ignore 6 ints, in example 0 0 0 -2 0 3
01030               next();
01031             if ( support_ids[ i_sub ] < 1 || support_ids[ i_sub ] > (int)medi->groupes.size() ) {
01032               INFOS_MED("Error of field reading: wrong mesh reference "<<
01033                     support_ids[ i_sub ] << DUMP_LINE_NB );
01034               return false;
01035             }
01036             if ( nb_comp[ i_sub ] < 0 /*1*/ ) { // [SALOME platform 0019886]
01037               INFOS_MED("Error of field reading: wrong nb of components " <<
01038                     nb_comp[ i_sub ] << DUMP_LINE_NB );
01039               return false;
01040             }
01041             total_nb_comp += nb_comp[ i_sub ];
01042           }
01043           for ( initNameReading( nb_sub, 17 ); more(); next() )
01044             ; // (4) dummy strings
01045           for ( initNameReading( nb_sub ); more(); next() )
01046             ; // (5) dummy strings
01047 
01048           // loop on subcomponents of a field, each of which refers to
01049           // a certain support and has its own number of components;
01050           // read component values
01051           _field<double>* fdouble = 0;
01052           _field<int>*    fint    = 0;
01053           _fieldBase *    fbase   = 0;
01054           for ( i_sub = 0; i_sub < nb_sub; ++ i_sub )
01055           {
01056             vector<string> comp_names( nb_comp[ i_sub ]), comp_type( nb_comp[ i_sub ]);
01057             for ( initIntReading( nb_comp[ i_sub ] ); more(); next() )
01058               ;  // (6) nb_comp addresses of MELVAL structure
01059 
01060             // (7) component names
01061             for ( initNameReading( nb_comp[ i_sub ] ); more(); next() )
01062               comp_names[ index() ] = getName();
01063 
01064             // (8) component type
01065             for ( initNameReading( nb_comp[ i_sub ], 17 ); more(); next() ) { // 17 is name width
01066               comp_type[ index() ] = getName();
01067               // component types must be the same
01068               if ( index() > 0 && comp_type[ index() ] != comp_type[ index() - 1] ) {
01069                 INFOS_MED( "Error of field reading: diff component types <"
01070                       << comp_type[ index() ] << "> != <" << comp_type[ index() - 1 ]
01071                        << ">" << DUMP_LINE_NB );
01072                 return false;
01073               }
01074             }
01075             // now type is known, create a field, one for all subs
01076             bool isReal = (nb_comp[i_sub] > 0) ? (comp_type[0] == "REAL*8") : true;
01077             if ( !ignoreField && !fbase && total_nb_comp ) {
01078               if ( !isReal ) {
01079                 fbase = fint = new _field<int>( MED_INT32, nb_sub, total_nb_comp );
01080                 INFOS_MED( "Warning: read NOT REAL field, type <" << comp_type[0] << ">"
01081                       << DUMP_LINE_NB);
01082               }
01083               else
01084                 fbase = fdouble = new _field<double>( MED_REEL64, nb_sub, total_nb_comp );
01085               medi->fields.push_back( cell_fields[ objet ] = fbase ); // medi->fields is a std::list
01086             }
01087             // store support id and nb components of a sub
01088             if ( fbase ) {
01089               fbase->_sub[ i_sub ].setData( nb_comp[ i_sub ], support_ids[ i_sub ]);
01090               fbase->_description = description;
01091             }
01092             // loop on components: read values
01093             for ( int i_comp = 0; i_comp < nb_comp[ i_sub ]; ++i_comp )
01094             {
01095               // (9) nb of values
01096 #ifdef HAS_XDR
01097               if(_is_xdr) initIntReading( 4 );
01098               else        initIntReading( 2 );
01099 #else
01100               initIntReading( 2 );
01101 #endif
01102               int nb_val_by_elem = getInt(); next();
01103               int nb_values      = getInt();
01104 #ifdef HAS_XDR
01105               if(_is_xdr) { next(); next(); next(); }
01106 #endif
01107               fbase->_sub[ i_sub ]._nb_gauss[ i_comp ] = nb_val_by_elem;
01108               // (10) values
01109               nb_values *= nb_val_by_elem;
01110               if ( fbase ) {
01111                 if ( isReal ) {
01112                   vector<double> & vals = fdouble->addComponent( nb_values );
01113                   for ( initDoubleReading( nb_values ); more(); next()) {
01114                     vals[ index() ] = getDouble();
01115                   }
01116                 }
01117                 else {
01118                   vector<int> & vals = fint->addComponent( nb_values );
01119                   for ( initIntReading( nb_values ); more(); next() ) {
01120                     vals[ index() ] = getInt();
01121                   }
01122                 }
01123                 // store component name
01124                 fbase->_sub[ i_sub ].compName( i_comp ) = comp_names[ i_comp ];
01125               }
01126               else {
01127                 for ( isReal ? initDoubleReading( nb_values ) : initIntReading( nb_values );
01128                       more();
01129                       next() ) ;
01130               }
01131             }
01132           } // loop on subcomponents of a field
01133 
01134           // set id of a group including all sub supports but only
01135           // if all subs have the same nb of components
01136           if ( fbase && fbase->hasSameComponentsBySupport() )
01137             fbase->_group_id = getGroupId( support_ids, medi );
01138 
01139         } // end loop on field objects
01140 
01141         // set field names
01142         setFieldNames( cell_fields, objets_nommes, indices_objets_nommes );
01143 
01144       } // numero_pile == PILE_FIELD && readFields
01145 
01146       // ---------------------------------------
01147       //                            MED NAMES
01148       // ---------------------------------------
01149 
01150       // IMP 0020434: mapping GIBI names to MED names
01151       else if (numero_pile == PILE_TABLES)
01152       {
01153         const char * table_med_mail = "MED_MAIL";
01154         const char * table_med_cham = "MED_CHAM";
01155         const char * table_med_comp = "MED_COMP";
01156 
01157         int table_med_mail_id = -1;
01158         int table_med_cham_id = -1;
01159         int table_med_comp_id = -1;
01160 
01161         for (int iname = 0; iname < nb_objets_nommes; iname++) {
01162           if (strcmp(objets_nommes[iname].c_str(), table_med_mail) == 0) {
01163             table_med_mail_id = indices_objets_nommes[iname];
01164           }
01165           else if (strcmp(objets_nommes[iname].c_str(), table_med_cham) == 0) {
01166             table_med_cham_id = indices_objets_nommes[iname];
01167           }
01168           else if (strcmp(objets_nommes[iname].c_str(), table_med_comp) == 0) {
01169             table_med_comp_id = indices_objets_nommes[iname];
01170           }
01171           else {
01172           }
01173         }
01174         //if (noms_med_id < 0) continue;
01175         if (table_med_mail_id < 0 && table_med_cham_id < 0 && table_med_comp_id < 0)
01176 #ifdef HAS_XDR
01177           if(!_is_xdr)
01178 #endif
01179             continue;
01180 
01181         for (int itable = 1; itable <= nb_objets; itable++) {
01182           // read tables "MED_MAIL", "MED_CHAM" and "MED_COMP", that keeps correspondence
01183           // between GIBI names (8 symbols if any) and MED names (possibly longer)
01184           initIntReading(1);
01185           int nb_table_vals = getInt(); next();
01186           if (nb_table_vals < 0) {
01187             INFOS_MED("Erreur de lecture dans enregistrement de pile " <<
01188                       PILE_TABLES << DUMP_LINE_NB );
01189             return false;
01190           }
01191 
01192           int name_i_med_pile;
01193           initIntReading(nb_table_vals);
01194           for (int i = 0; i < nb_table_vals/4; i++)
01195           {
01196             if (itable == table_med_mail_id ||
01197                 itable == table_med_cham_id ||
01198                 itable == table_med_comp_id)
01199             {
01200               nameGIBItoMED name_i;
01201               name_i_med_pile  = getInt(); next();
01202               name_i.med_id    = getInt(); next();
01203               name_i.gibi_pile = getInt(); next();
01204               name_i.gibi_id   = getInt(); next();
01205 
01206               if (name_i_med_pile != PILE_STRINGS) {
01207                 // error: med(long) names are always kept in PILE_STRINGS
01208               }
01209 
01210               if (itable == table_med_mail_id) {
01211                 if (name_i.gibi_pile != PILE_SOUS_MAILLAGE) {
01212                   // error: must be PILE_SOUS_MAILLAGE
01213                 }
01214                 listGIBItoMED_mail.push_back(name_i);
01215               }
01216               else if (itable == table_med_cham_id) {
01217                 if (name_i.gibi_pile != PILE_FIELD &&
01218                     name_i.gibi_pile != PILE_NODES_FIELD) {
01219                   // error: must be PILE_FIELD or PILE_NODES_FIELD
01220                 }
01221                 listGIBItoMED_cham.push_back(name_i);
01222               }
01223               else if (itable == table_med_comp_id) {
01224                 if (name_i.gibi_pile != PILE_STRINGS) {
01225                   // error: gibi(short) names of components are kept in PILE_STRINGS
01226                 }
01227                 listGIBItoMED_comp.push_back(name_i);
01228               }
01229               else {
01230               }
01231             }
01232             else
01233             {
01234               // pass table
01235               next(); next(); next(); next();
01236             }
01237           }
01238         } // for (int itable = 0; itable < nb_objets; itable++)
01239       } // numero_pile == PILE_TABLES
01240 
01241       // ---------------------------------------
01242       //                            MED NAMES
01243       // ---------------------------------------
01244 
01245       // IMP 0020434: mapping GIBI names to MED names
01246       else if (numero_pile == PILE_STRINGS)
01247       {
01248         initIntReading(2);
01249         int stringLen = getInt(); next();
01250         int nbSubStrings = getInt(); next();
01251         if (nbSubStrings != nb_objets) {
01252           // error
01253         }
01254         string aWholeString;
01255 #ifdef HAS_XDR
01256         if(_is_xdr)
01257           {
01258             const int fixedLength = 71;
01259             while ((int)aWholeString.length() < stringLen) {
01260               int remainLen = stringLen - aWholeString.length();
01261               int len;
01262               if ( remainLen > fixedLength )
01263                 {
01264                   len = fixedLength;
01265                 }
01266               else
01267                 {
01268                   len = remainLen;
01269                 }
01270               initNameReading(1, len);
01271               aWholeString += getName();
01272               next();
01273             }
01274           }
01275         else
01276           {
01277 #endif
01278             string aCurrLine;
01279             const int fixedLength = 71;
01280             while ((int)aWholeString.length() < stringLen) {
01281               getNextLine( ligne );
01282               int remainLen = stringLen - aWholeString.length();
01283               if ( remainLen > fixedLength )
01284                 {
01285                   aWholeString += ligne + 1;
01286                 }
01287               else
01288                 {
01289                   aWholeString += ligne + ( 72 - remainLen );
01290                 }
01291             }
01292 #ifdef HAS_XDR
01293           }
01294 #endif
01295         int prevOffset = 0;
01296         int currOffset = 0;
01297         initIntReading(nbSubStrings);
01298         for (int istr = 1; istr <= nbSubStrings; istr++, next()) {
01299           currOffset = getInt();
01300           // fill mapStrings
01301           mapStrings[istr] = aWholeString.substr(prevOffset, currOffset - prevOffset);
01302           prevOffset = currOffset;
01303         }
01304       }
01305 
01306       else if ( numero_pile >= PILE_LAST_READABLE )
01307         break; // stop file reading
01308 
01309     } // Fin case ENREG_TYPE_2
01310 #ifdef HAS_XDR
01311     else if (numero_enregistrement == ENREG_TYPE_5 )
01312     {
01313       if(_is_xdr)
01314         {
01315           break;
01316         }
01317     }
01318 #endif
01319 #ifdef HAS_XDR
01320     else
01321     {
01322       if(_is_xdr)
01323         {
01324           cout << "XDR : ENREGISTREMENT DE TYPE " << numero_enregistrement << " not implemented !!!" << endl;
01325           throw MEDEXCEPTION("XDR : ENREGISTREMENT DE TYPE not implemented !!!");
01326         }
01327     }
01328 #endif
01329   } //  fin de la boucle while de lecture externe
01330 
01331   // IMP 0020434: mapping GIBI names to MED names
01332   // set med names to objects (mesh, fields, support, group or other)
01333   if (listGIBItoMED_mail.size() > 0) {
01334     set<int> treatedGroups;
01335     list<nameGIBItoMED>::iterator itGIBItoMED = listGIBItoMED_mail.begin();
01336     for (; itGIBItoMED != listGIBItoMED_mail.end(); itGIBItoMED++) {
01337       if ( (int)medi->groupes.size() < itGIBItoMED->gibi_id ) continue;
01338       _groupe & grp = medi->groupes[itGIBItoMED->gibi_id - 1];
01339       // if there are several names for grp then the 1st name is the name
01340       // of grp and the rest ones are names of groups referring grp (issue 0021311)
01341       const bool isRefName = !treatedGroups.insert( itGIBItoMED->gibi_id ).second;
01342       if ( !isRefName )
01343         grp.nom = mapStrings[ itGIBItoMED->med_id ];
01344       else
01345         for ( unsigned i = 0; i < grp.refNames.size(); ++i )
01346           if ( grp.refNames[i].empty() )
01347             grp.refNames[i] = mapStrings[ itGIBItoMED->med_id ];
01348     } // iterate on listGIBItoMED_mail
01349   }
01350   if (listGIBItoMED_cham.size() > 0) {
01351     list<nameGIBItoMED>::iterator itGIBItoMED = listGIBItoMED_cham.begin();
01352     for (; itGIBItoMED != listGIBItoMED_cham.end(); itGIBItoMED++) {
01353       if (itGIBItoMED->gibi_pile == PILE_FIELD) {
01354         cell_fields[itGIBItoMED->gibi_id - 1]->_name = mapStrings[itGIBItoMED->med_id];
01355       }
01356       else if (itGIBItoMED->gibi_pile == PILE_NODES_FIELD) {
01357         node_fields[itGIBItoMED->gibi_id - 1]->_name = mapStrings[itGIBItoMED->med_id];
01358       }
01359       else {
01360       }
01361     } // iterate on listGIBItoMED_cham
01362   }
01363   if (listGIBItoMED_comp.size() > 0) {
01364     list<nameGIBItoMED>::iterator itGIBItoMED = listGIBItoMED_comp.begin();
01365     for (; itGIBItoMED != listGIBItoMED_comp.end(); itGIBItoMED++)
01366       {
01367         string medName  = mapStrings[itGIBItoMED->med_id];
01368         string gibiName = mapStrings[itGIBItoMED->gibi_id];
01369 
01370         bool name_found = false;
01371         for ( int isNodal = 0; isNodal < 2 && !name_found; ++isNodal )
01372           {
01373             vector<_fieldBase*> & fields = isNodal ? node_fields : cell_fields;
01374             for ( unsigned ifi = 0; ifi < fields.size() && !name_found; ifi++)
01375               {
01376                 if (medName.find( fields[ifi]->_name + "." ) == 0 ) {
01377                   std::vector<_fieldBase::_sub_data>& aSubDs = fields[ifi]->_sub;
01378                   int nbSub = aSubDs.size();
01379                   for (int isu = 0; isu < nbSub; isu++) {
01380                     for (int ico = 0; ico < aSubDs[isu].nbComponents(); ico++) {
01381                       if (aSubDs[isu].compName(ico) == gibiName) {
01382                         string medNameCompo = medName.substr( fields[ifi]->_name.size() + 1 );
01383                         fields[ifi]->_sub[isu].compName(ico) = medNameCompo;
01384                       }
01385                     }
01386                   }
01387                 }
01388               }
01389           }
01390       } // iterate on listGIBItoMED_comp
01391   }
01392 
01393   // check if all needed piles present
01394   if ( donePiles.find( PILE_SOUS_MAILLAGE ) != donePiles.end() )
01395     {
01396       if (donePiles.find( PILE_NOEUDS ) == donePiles.end() ) {
01397         INFOS_MED( " Missing pile " << PILE_NOEUDS );
01398         return false;
01399       }
01400       if (donePiles.find( PILE_COORDONNEES ) == donePiles.end()) {
01401         INFOS_MED( " Missing pile " << PILE_COORDONNEES );
01402         return false;
01403       }
01404     }
01405 
01406   END_OF_MED(LOC);
01407   return true;
01408 }
01409 
01410 GIBI_MESH_DRIVER::GIBI_MESH_DRIVER():
01411        GENDRIVER(GIBI_DRIVER),
01412        _mesh(( GMESH *) NULL),
01413        _meshName("")
01414 {
01415   MESSAGE_MED("GIBI_MESH_DRIVER()");
01416 }
01417 
01418 GIBI_MESH_DRIVER::GIBI_MESH_DRIVER(const string &         fileName,
01419                                    GMESH *                ptrMesh,
01420                                    MED_EN::med_mode_acces accessMode):
01421   GENDRIVER(fileName, accessMode, GIBI_DRIVER),
01422   _mesh(ptrMesh)
01423 {
01424   MESSAGE_MED( "GIBI_MESH_DRIVER(" << fileName <<","<<accessMode );
01425   // mesh name construction from fileName
01426   const string ext=".sauv"; // expected extension
01427   int pos=fileName.find(ext,0);
01428   int pos1=fileName.rfind('/');
01429   if ( pos < 0 || pos >= (int)fileName.size() ) pos = fileName.size();
01430 #ifdef WNT
01431   if ( pos1 < 0 || pos1 >= (int)fileName.size() ) pos1 = fileName.rfind('\\');
01432 #endif
01433   if ( pos1 < 0 || pos1 >= (int)fileName.size() ) pos1 = -1;
01434   _meshName = string(fileName,pos1+1,pos-pos1-1); //get rid of directory & extension
01435   SCRUTE_MED(_meshName);
01436 }
01437 
01438 GIBI_MESH_DRIVER::GIBI_MESH_DRIVER(const GIBI_MESH_DRIVER & driver):
01439   GENDRIVER(driver),
01440   _mesh(driver._mesh),
01441   _meshName(driver._meshName)
01442 {
01443   MESSAGE_MED("GIBI_MESH_DRIVER(const GIBI_MESH_DRIVER & driver)");
01444 }
01445 
01446 GIBI_MESH_DRIVER::~GIBI_MESH_DRIVER()
01447 {
01448   MESSAGE_MED("~GIBI_MESH_DRIVER()");
01449 }
01450 void    GIBI_MESH_DRIVER::setMeshName(const string & meshName) { _meshName = meshName; }
01451 string  GIBI_MESH_DRIVER::getMeshName() const { return _meshName; }
01452 
01453 
01454 //---------------------------------- RDONLY PART ------------------------------------------
01455 
01456 GIBI_MESH_RDONLY_DRIVER::GIBI_MESH_RDONLY_DRIVER():
01457   GIBI_MESH_DRIVER(),
01458   _File (-1),_start(0L),_ptr  (0L),_eptr (0L)
01459 {
01460 }
01461 GIBI_MESH_RDONLY_DRIVER::GIBI_MESH_RDONLY_DRIVER(const string & fileName,MESH * ptrMesh):
01462   GIBI_MESH_DRIVER(fileName,ptrMesh,RDONLY),
01463   _File (-1),_start(0L),_ptr  (0L),_eptr (0L)
01464 {
01465   MESSAGE_MED("GIBI_MESH_RDONLY_DRIVER::GIBI_MESH_RDONLY_DRIVER"
01466               "(const string & fileName, MESH * ptrMesh) has been created, "
01467               << fileName << ", " << RDONLY);
01468 }
01469 GIBI_MESH_RDONLY_DRIVER::GIBI_MESH_RDONLY_DRIVER(const GIBI_MESH_RDONLY_DRIVER & driver):
01470   GIBI_MESH_DRIVER(driver),
01471   _File (-1),_start(0L),_ptr  (0L),_eptr (0L)
01472 {
01473 }
01474 
01475 GIBI_MESH_RDONLY_DRIVER::~GIBI_MESH_RDONLY_DRIVER()
01476 {
01477   const char* LOC = "~GIBI_MESH_RDONLY_DRIVER()";
01478   BEGIN_OF_MED(LOC);
01479   if (_File >= 0)
01480   {
01481 #ifdef HAS_XDR
01482     if(_is_xdr)
01483       {
01484         xdr_destroy((XDR*)_xdrs);
01485         free((XDR*)_xdrs);
01486         fclose(_xdrs_file);
01487       }
01488 #endif
01489     ::close (_File);
01490     if (_start != 0L)
01491       delete [] _start;
01492   }
01493   MESSAGE_MED("GIBI_MESH_RDONLY_DRIVER::~GIBI_MESH_RDONLY_DRIVER() has been destroyed");
01494 }
01495 GENDRIVER * GIBI_MESH_RDONLY_DRIVER::copy(void) const
01496 {
01497   return new GIBI_MESH_RDONLY_DRIVER(*this);
01498 }
01499 
01500 //=======================================================================
01501 //function : open
01502 //purpose  :
01503 //=======================================================================
01504 
01505 const int GIBI_MaxOutputLen   = 150;
01506 const int GIBI_BufferSize     = 16184; // for non-stream input
01507 
01508 void GIBI_MESH_RDONLY_DRIVER::open()
01509   //     throw (MEDEXCEPTION)
01510 {
01511   if( _status == MED_OPENED )
01512     return;
01513 
01514   const char * LOC = "GIBI_MESH_RDONLY_DRIVER::open()";
01515   BEGIN_OF_MED(LOC);
01516 
01517 //   MED_EN::med_mode_acces aMode = getAccessMode();
01518 //   if ( aMode != MED_EN::MED_LECT && aMode != MED_EN::MED_REMP )
01519 //     throw MEDEXCEPTION(LOCALIZED(STRING(LOC) << " Bad file mode access ! " << aMode));
01520 
01521 #ifdef WNT
01522   _File = ::_open (_fileName.c_str(), _O_RDONLY|_O_BINARY);
01523 #else
01524   _File = ::open (_fileName.c_str(), O_RDONLY);
01525 #endif
01526   if (_File >= 0)
01527   {
01528     _start = new char [GIBI_BufferSize];
01529     _ptr   = _start;
01530     _eptr  = _start;
01531     _status = MED_OPENED;
01532     _lineNb = 0;
01533   }
01534   else
01535   {
01536     _status = MED_CLOSED;
01537     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<" Could not open file "<<_fileName
01538                                  << " fd: " << _File));
01539   }
01540 
01541   // xdr
01542   
01543 #ifdef HAS_XDR
01544   _is_xdr = false;
01545   _xdrs_file = fdopen(_File, "r");
01546   _xdrs = (XDR *)malloc(sizeof(XDR));
01547   
01548   xdrstdio_create((XDR*)_xdrs, _xdrs_file, XDR_DECODE);
01549   
01550   const int maxsize = 10;
01551   char icha[maxsize+1];
01552   char *icha2=icha;
01553   bool_t xdr_test = xdr_string((XDR*)_xdrs, &icha2, maxsize);
01554   if(xdr_test)
01555     {
01556       icha[maxsize] = '\0';
01557       if(!strcmp(icha, "CASTEM XDR"))
01558         {
01559           _is_xdr = true;
01560         }
01561     }
01562   
01563   if(! _is_xdr)
01564     {
01565       xdr_destroy((XDR*)_xdrs);
01566       free((XDR*)_xdrs);
01567       fclose(_xdrs_file);
01568 #ifdef WNT
01569       _File = ::_open (_fileName.c_str(), _O_RDONLY|_O_BINARY);
01570 #else
01571       ::close (_File); // ? needed ?
01572       _File = ::open (_fileName.c_str(), O_RDONLY);
01573 #endif
01574     }
01575 #endif
01576   
01577   END_OF_MED(LOC);
01578 }
01579 
01580 //=======================================================================
01581 //function : close
01582 //purpose  :
01583 //=======================================================================
01584 
01585 void GIBI_MESH_RDONLY_DRIVER::close()
01586 {
01587   const char* LOC = "GIBI_MESH_DRIVER::close() ";
01588   BEGIN_OF_MED(LOC);
01589   if ( _status == MED_OPENED) {
01590     if (_File >= 0) {
01591 #ifdef HAS_XDR
01592       if(_is_xdr)
01593         {
01594           xdr_destroy((XDR*)_xdrs);
01595           free((XDR*)_xdrs);
01596           fclose(_xdrs_file);
01597         }
01598 #endif
01599       ::close (_File);
01600       if (_start != 0L)
01601         delete [] _start;
01602       _File = -1;
01603     }
01604     _status = MED_CLOSED;
01605   }
01606   END_OF_MED(LOC);
01607 }
01608 
01609 //=======================================================================
01610 //function : getLine
01611 //purpose  :
01612 //=======================================================================
01613 
01614 bool GIBI_MESH_RDONLY_DRIVER::getLine(char* & aLine)
01615 {
01616 #ifdef HAS_XDR
01617   if (_is_xdr) return true;
01618 #endif
01619   bool aResult = true;
01620   // Check the state of the buffer;
01621   // if there is too little left, read the next portion of data
01622   int nBytesRest = _eptr - _ptr;
01623   if (nBytesRest < GIBI_MaxOutputLen)
01624   {
01625     if (nBytesRest > 0) {
01626       //memcpy (_start, _ptr, nBytesRest);
01627       char* tmpBuf = new char [nBytesRest];
01628       memcpy (tmpBuf, _ptr, nBytesRest);
01629       memcpy (_start, tmpBuf, nBytesRest);
01630       delete [] tmpBuf;
01631     } else
01632       nBytesRest = 0;
01633     _ptr = _start;
01634     const int nBytesRead = ::read (_File,
01635                                    &_start [nBytesRest],
01636                                    GIBI_BufferSize - nBytesRest);
01637     nBytesRest += nBytesRead;
01638     _eptr = &_start [nBytesRest];
01639   }
01640   // Check the buffer for the end-of-line
01641   char * ptr = _ptr;
01642   while (~0)
01643   {
01644     // Check for end-of-the-buffer, the ultimate criterion for termination
01645     if (ptr >= _eptr)
01646     {
01647       if (nBytesRest <= 0)
01648         aResult = false;
01649       else
01650         _eptr[-1] = '\0';
01651       break;
01652     }
01653     // seek the line-feed character
01654     if (ptr[0] == '\n')
01655     {
01656       if (ptr[-1] == '\r')
01657         ptr[-1] = '\0';
01658       ptr[0] = '\0';
01659       ++ptr;
01660       break;
01661     }
01662     ++ptr;
01663   }
01664   // Output the result
01665   aLine = _ptr;
01666   _ptr = ptr;
01667   _lineNb++;
01668 
01669   return aResult;
01670 }
01671 
01672 //=======================================================================
01673 //function : initNameReading
01674 //purpose  :
01675 //=======================================================================
01676 
01677 void GIBI_MESH_RDONLY_DRIVER::initNameReading(int nbValues, int width)
01678 {
01679 #ifdef HAS_XDR
01680   if(_is_xdr)
01681     {
01682       _xdr_kind = _xdr_kind_char;
01683       if(nbValues)
01684         {
01685           unsigned int nels = nbValues*width;
01686           _xdr_cvals = (char*)malloc((nels+1)*sizeof(char));
01687           xdr_string((XDR*)_xdrs, &_xdr_cvals, nels);
01688           _xdr_cvals[nels] = '\0';
01689         }
01690     }
01691 #endif
01692   init( nbValues, 72 / ( width + 1 ), width, 1 );
01693 }
01694 
01695 //=======================================================================
01696 //function : initIntReading
01697 //purpose  :
01698 //=======================================================================
01699 
01700 void GIBI_MESH_RDONLY_DRIVER::initIntReading(int nbValues)
01701 {
01702 #ifdef HAS_XDR
01703   if(_is_xdr)
01704     {
01705       _xdr_kind = _xdr_kind_int;
01706       if(nbValues)
01707         {
01708           unsigned int nels = nbValues;
01709           unsigned int actual_nels;
01710           _xdr_ivals = (int*)malloc(nels*sizeof(int));
01711           xdr_array((XDR*)_xdrs, (char **)&_xdr_ivals, &actual_nels, nels, sizeof(int), (xdrproc_t)xdr_int);
01712         }
01713     }
01714 #endif
01715   init( nbValues, 10, 8 );
01716 }
01717 
01718 //=======================================================================
01719 //function : initDoubleReading
01720 //purpose  :
01721 //=======================================================================
01722 
01723 void GIBI_MESH_RDONLY_DRIVER::initDoubleReading(int nbValues)
01724 {
01725 #ifdef HAS_XDR
01726   if(_is_xdr)
01727     {
01728       _xdr_kind = _xdr_kind_double;
01729       if(nbValues)
01730         {
01731           unsigned int nels = nbValues;
01732           unsigned int actual_nels;
01733           _xdr_dvals = (double*)malloc(nels*sizeof(double));
01734           xdr_array((XDR*)_xdrs, (char **)&_xdr_dvals, &actual_nels, nels, sizeof(double), (xdrproc_t)xdr_double);
01735         }
01736     }
01737 #endif
01738   init( nbValues, 3, 22 );
01739 }
01740 
01741 //=======================================================================
01742 //function : init
01743 //purpose  :
01744 //=======================================================================
01745 
01746 void GIBI_MESH_RDONLY_DRIVER::init( int nbToRead, int nbPosInLine, int width, int shift )
01747 {
01748 #ifdef HAS_XDR
01749   if(_is_xdr)
01750     {
01751       if(_iRead < _nbToRead)
01752         {
01753           cout << "_iRead, _nbToRead : " << _iRead << " " << _nbToRead << endl;
01754           cout << "Unfinished iteration before new one !" << endl;
01755           throw MEDEXCEPTION("Unfinished iteration before new one !");
01756         }
01757     }
01758 #endif
01759   _nbToRead = nbToRead;
01760   _nbPosInLine = nbPosInLine;
01761   _width = width;
01762   _shift = shift;
01763   _iPos = _iRead = 0;
01764   if ( _nbToRead ) {
01765     getNextLine( _curPos );
01766     _curPos = _curPos + _shift;
01767   }
01768   else
01769     _curPos = 0;
01770 #ifdef HAS_XDR
01771   if(_is_xdr && (_xdr_kind == _xdr_kind_char))
01772     _curPos = _xdr_cvals;
01773 #endif
01774 }
01775 
01776 //=======================================================================
01777 //function : more
01778 //purpose  :
01779 //=======================================================================
01780 
01781 bool GIBI_MESH_RDONLY_DRIVER::more() const
01782 {
01783   bool result = false;
01784   if(_iRead < _nbToRead)
01785     {
01786       if(_curPos) result = true;
01787 #ifdef HAS_XDR
01788       if(_is_xdr) result = true;
01789 #endif
01790     }
01791   return result;
01792 }
01793 
01794 //=======================================================================
01795 //function : next
01796 //purpose  : line getting
01797 //=======================================================================
01798 
01799 void GIBI_MESH_RDONLY_DRIVER::next()
01800 {
01801   if ( !more() ) throw MEDEXCEPTION(LOCALIZED("!more()"));
01802   ++_iRead;
01803   ++_iPos;
01804   if ( _iRead < _nbToRead ) {
01805     if ( _iPos >= _nbPosInLine ) {
01806       getNextLine( _curPos );
01807       _curPos = _curPos + _shift;
01808       _iPos = 0;
01809     }
01810     else
01811       _curPos = _curPos + _width + _shift;
01812 #ifdef HAS_XDR
01813     if(_is_xdr && (_xdr_kind == _xdr_kind_char))
01814       {
01815         _curPos = _xdr_cvals + _iRead*_width;
01816       }
01817 #endif
01818   }
01819   else
01820     {
01821 #ifdef HAS_XDR
01822       if(_is_xdr)
01823         {
01824           if(_xdr_kind == _xdr_kind_char) free(_xdr_cvals);
01825           if(_xdr_kind == _xdr_kind_int) free(_xdr_ivals);
01826           if(_xdr_kind == _xdr_kind_double) free(_xdr_dvals);
01827           _xdr_kind = _xdr_kind_null;
01828         }
01829 #endif
01830       _curPos = 0;
01831     }
01832 }
01833 
01834 //=======================================================================
01835 //function : getName
01836 //purpose  : names reading
01837 //=======================================================================
01838 
01839 string GIBI_MESH_RDONLY_DRIVER::getName() const
01840 {
01841   int len = _width;
01842   while (( _curPos[len-1] == ' ' || _curPos[len-1] == 0) && len > 0 )
01843     len--;
01844   return string( _curPos, len );
01845 }
01846 
01847 //=======================================================================
01848 //function : getInt
01849 //purpose  : int reading
01850 //=======================================================================
01851 
01852 int GIBI_MESH_RDONLY_DRIVER::getInt() const
01853 {
01854 #ifdef HAS_XDR
01855   if(_is_xdr)
01856     {
01857       if(_iRead < _nbToRead)
01858         {
01859           return _xdr_ivals[_iRead];
01860         }
01861       else
01862         {
01863           int result;
01864           xdr_int((XDR*)_xdrs, &result);
01865           return result;
01866         }
01867     }
01868 #endif
01869   // fix for two glued ints (issue 0021009):
01870   // Line nb    |   File contents
01871   // ------------------------------------------------------------------------------------
01872   // 53619905   |       1       2       6       8
01873   // 53619906   |                                                                SCALAIRE
01874   // 53619907   |    -63312600499       1       0       0       0      -2       0       2
01875   //   where -63312600499 is actualy -633 and 12600499
01876   char hold=_curPos[_width];
01877   _curPos[_width] = '\0';
01878   int result = atoi(str());
01879   _curPos[_width] = hold;
01880   return result;
01881   //return atoi(str());
01882 }
01883 
01884 //=======================================================================
01885 //function : getFloat
01886 //purpose  : float reading
01887 //=======================================================================
01888 
01889 float GIBI_MESH_RDONLY_DRIVER::getFloat() const
01890 {
01891 #ifdef HAS_XDR
01892   if(_is_xdr)
01893     {
01894       float result;
01895       xdr_float((XDR*)_xdrs, &result);
01896       return result;
01897     }
01898 #endif
01899   return getDouble();
01900 }
01901 
01902 //=======================================================================
01903 //function : getDouble
01904 //purpose  : double reading
01905 //=======================================================================
01906 
01907 double GIBI_MESH_RDONLY_DRIVER::getDouble() const
01908 {
01909 #ifdef HAS_XDR
01910   if(_is_xdr)
01911     {
01912       if(_iRead < _nbToRead)
01913         {
01914           return _xdr_dvals[_iRead];
01915         }
01916       else
01917         {
01918           double result;
01919           xdr_double((XDR*)_xdrs, &result);
01920           return result;
01921         }
01922     }
01923 #endif
01924   
01925   //return atof(str());
01926 
01927   std::string aStr (str());
01928 
01929   // Correction 1: add missing 'E' specifier
01930   int aPosStart = aStr.find_first_not_of(" \t");
01931   if (aPosStart < (int)aStr.length()) {
01932     int aPosSign = aStr.find_first_of("+-", aPosStart + 1); // pass the leading symbol, as it can be a sign
01933     if (aPosSign < (int)aStr.length()) {
01934       if (aStr[aPosSign - 1] != 'e' && aStr[aPosSign - 1] != 'E')
01935         aStr.insert(aPosSign, "E", 1);
01936     }
01937   }
01938 
01939   // Correction 2: set "C" numeric locale to read numbers
01940   // with dot decimal point separator, as it is in SAUVE files
01941   //char* aCurLocale = setlocale(LC_NUMERIC, 0);
01942   std::string aCurLocale = setlocale(LC_NUMERIC, 0);
01943   setlocale(LC_NUMERIC, "C");
01944   double ret = atof(aStr.data());
01945   //setlocale(LC_NUMERIC, aCurLocale);
01946   setlocale(LC_NUMERIC, aCurLocale.data());
01947 
01948   return ret;
01949 }
01950 
01951 //=======================================================================
01952 //function : read
01953 //purpose  :
01954 //=======================================================================
01955 
01956 void GIBI_MESH_RDONLY_DRIVER::read(void) throw (MEDEXCEPTION)
01957 {
01958   const char * LOC = "_GIBI_RDONLY_DRIVER::read() : ";
01959   BEGIN_OF_MED(LOC);
01960 
01961   if (_status!=MED_OPENED)
01962     throw MEDEXCEPTION(LOCALIZED(STRING(LOC) << "The _idt of file " << _fileName << " is : "
01963                                  <<  " (the file is not opened)." ));
01964   if ( ! _mesh->isEmpty() )
01965     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Mesh object not empty : can't fill it!"));
01966 
01967   _intermediateMED medi;
01968   try {
01969     if ( readFile( &medi, false )) {
01970       // impression résultats
01971       MESSAGE_MED(LOC << "GIBI_MESH_RDONLY_DRIVER::read : RESULTATS STRUCTURE INTERMEDIAIRES : ");
01972       MESSAGE_MED(LOC <<  medi );
01973 
01974       fillMesh( &medi );
01975       updateSupports(); // create families from groups etc.
01976     }
01977   }
01978   catch (MEDEXCEPTION &ex)
01979   {
01980     INFOS_MED( ex.what() );
01981   }
01982   END_OF_MED(LOC);
01983 }
01984 
01985 //=======================================================================
01986 //function : getReverseVector
01987 //purpose  :
01988 //=======================================================================
01989 
01990 static void getReverseVector (const medGeometryElement type,
01991                               vector<pair<int,int> > & swapVec )
01992 {
01993   const char* LOC = "void getReverseVector()";
01994   BEGIN_OF_MED(LOC);
01995   swapVec.clear();
01996 
01997   switch ( type ) {
01998   case MED_TETRA4:
01999     swapVec.resize(1);
02000     swapVec[0] = make_pair( 1, 2 );
02001     break;
02002   case MED_PYRA5:
02003     swapVec.resize(1);
02004     swapVec[0] = make_pair( 1, 3 );
02005     break;
02006   case MED_PENTA6:
02007     swapVec.resize(2);
02008     swapVec[0] = make_pair( 1, 2 );
02009     swapVec[1] = make_pair( 4, 5 );
02010     break;
02011   case MED_HEXA8:
02012     swapVec.resize(2);
02013     swapVec[0] = make_pair( 1, 3 );
02014     swapVec[1] = make_pair( 5, 7 );
02015     break;
02016   case MED_TETRA10:
02017     swapVec.resize(3);
02018     swapVec[0] = make_pair( 1, 2 );
02019     swapVec[1] = make_pair( 4, 6 );
02020     swapVec[2] = make_pair( 8, 9 );
02021     break;
02022   case MED_PYRA13:
02023     swapVec.resize(4);
02024     swapVec[0] = make_pair( 1, 3 );
02025     swapVec[1] = make_pair( 5, 8 );
02026     swapVec[2] = make_pair( 6, 7 );
02027     swapVec[3] = make_pair( 10, 12 );
02028     break;
02029   case MED_PENTA15:
02030     swapVec.resize(4);
02031     swapVec[0] = make_pair( 1, 2 );
02032     swapVec[1] = make_pair( 4, 5 );
02033     swapVec[2] = make_pair( 6, 8 );
02034     swapVec[3] = make_pair( 9, 11 );
02035     break;
02036   case MED_HEXA20:
02037     swapVec.resize(7);
02038     swapVec[0] = make_pair( 1, 3 );
02039     swapVec[1] = make_pair( 5, 7 );
02040     swapVec[2] = make_pair( 8, 11 );
02041     swapVec[3] = make_pair( 9, 10 );
02042     swapVec[4] = make_pair( 12, 15 );
02043     swapVec[5] = make_pair( 13, 14 );
02044     swapVec[6] = make_pair( 17, 19 );
02045     break;
02046 //   case MED_SEG3: no need to reverse edges
02047 //     swapVec.resize(1);
02048 //     swapVec[0] = make_pair( 1, 2 );
02049 //     break;
02050   case MED_TRIA6:
02051     swapVec.resize(2);
02052     swapVec[0] = make_pair( 1, 2 );
02053     swapVec[1] = make_pair( 3, 5 );
02054     break;
02055   case MED_QUAD8:
02056     swapVec.resize(3);
02057     swapVec[0] = make_pair( 1, 3 );
02058     swapVec[1] = make_pair( 4, 7 );
02059     swapVec[2] = make_pair( 5, 6 );
02060     break;
02061   default:;
02062   }
02063   END_OF_MED(LOC);
02064 }
02065 
02066 //=======================================================================
02067 //function : reverse
02068 //purpose  : inverse element orientation using vector of indices to swap
02069 //=======================================================================
02070 
02071 static void reverse(const _maille & aMaille, const vector<pair<int,int> > & swapVec )
02072 {
02073   _maille* ma = (_maille*) & aMaille;
02074   for ( unsigned i = 0; i < swapVec.size(); ++i ) {
02075     std::swap( ma->sommets[ swapVec[i].first ],
02076                ma->sommets[ swapVec[i].second ]);
02077   }
02078   if ( swapVec.empty() )
02079     ma->reverse = true;
02080   else
02081     ma->reverse = false;
02082 }
02083 
02084 //=======================================================================
02085 //function : getGibi2MedConnectivity
02086 //purpose  : return array of indices to transform GIBI connectivity to MED one
02087 //=======================================================================
02088 
02089 static const int * getGibi2MedConnectivity( const medGeometryElement type )
02090 {
02091   static vector<const int*> conn;
02092   static int hexa20 [] = {0,6,4,2, 12,18,16,14, 7,5,3,1, 19,17,15,13, 8,11,10,9};
02093   static int penta15[] = {0,2,4, 9,11,13, 1,3,5, 10,12,14, 6,7,3};
02094   static int pyra13 [] = {0,2,4,6, 12, 1,3,5,7, 8,9,10,11};
02095   static int tetra10[] = {0,2,4, 9, 1,3,5, 6,7,8};
02096   static int quad8  [] = {0,2,4,6, 1,3,5,7};
02097   static int tria6  [] = {0,2,4, 1,3,5};
02098   static int seg3   [] = {0,2,1};
02099   if ( conn.empty() ) {
02100     conn.resize( MED_HEXA20 + 1, 0 );
02101     conn[ MED_HEXA20 ] = hexa20;
02102     conn[ MED_PENTA15] = penta15;
02103     conn[ MED_PYRA13 ] = pyra13;
02104     conn[ MED_TETRA10] = tetra10;
02105     conn[ MED_SEG3   ] = seg3;
02106     conn[ MED_TRIA6  ] = tria6;
02107     conn[ MED_QUAD8  ] = quad8;
02108   }
02109   return conn[ type ];
02110 }
02111 
02112 //=======================================================================
02113 //function : fixConnectivity
02114 //purpose  : GIBI connectivity -> MED one
02115 //=======================================================================
02116 
02117 static inline void fixConnectivity(const _maille & aMaille )
02118 {
02119   if ( const int * conn = getGibi2MedConnectivity( aMaille.geometricType )) {
02120     _maille* ma = (_maille*) & aMaille;
02121     //cout << "###### BEFORE fixConnectivity() " << *ma << endl;
02122     vector< _maille::TNoeud > newSommets( ma->sommets.size() );
02123     for ( unsigned i = 0; i < newSommets.size(); ++i )
02124       newSommets[ i ] = ma->sommets[ conn[ i ]];
02125     ma->sommets = newSommets;
02126     //cout << "###### AFTER fixConnectivity() " << *ma << endl;
02127   }
02128 }
02129 
02130 //=======================================================================
02131 //function : orientElements
02132 //purpose  :
02133 //=======================================================================
02134 
02135 static void orientElements( _intermediateMED& medi )
02136 {
02137   MESSAGE_MED("orientElements()");
02138 
02139   set<_maille>::const_iterator elemIt, elemEnd;
02140 
02141   int type = -100;
02142   vector< pair<int,int> > swapVec;
02143 
02144   bool isQuadratic = false;
02145 
02146   if ( medi.points.begin()->second.coord.size() == 2 ) { // space dimension
02147 
02148     // fix connectivity of quadratic edges
02149     _maillageByDimIterator edgesIt( medi, /*dim=*/1);
02150     while ( const set<_maille > * edges = edgesIt.nextType() )
02151     {
02152       isQuadratic = getGibi2MedConnectivity( edgesIt.type() );
02153       if (isQuadratic )
02154       {
02155         elemIt = edges->begin(), elemEnd = edges->end();
02156         for ( ; elemIt != elemEnd; ++elemIt )
02157           fixConnectivity( *elemIt );
02158       }
02159     }
02160     // --------------------------
02161     // Orient 2D faces clockwise
02162     // --------------------------
02163 
02164     _maillageByDimIterator faceMailIt( medi, /*dim=*/2 );
02165     while ( const set<_maille > * faces = faceMailIt.nextType() )
02166     {
02167       isQuadratic = getGibi2MedConnectivity( faceMailIt.type() );
02168       elemIt = faces->begin(), elemEnd = faces->end();
02169       for ( ; elemIt != elemEnd; elemIt++ )
02170       {
02171         // fix connectivity of quadratic faces
02172         if ( isQuadratic )
02173           fixConnectivity( *elemIt );
02174 
02175         // look for index of the most left node
02176         int iLeft = 0, iNode, nbNodes = elemIt->sommets.size();
02177         if ( nbNodes > 4 ) // quadratic face
02178           nbNodes /= 2;
02179         double minX = elemIt->sommets[0]->second.coord[0];
02180         for ( iNode = 1; iNode < nbNodes; ++iNode )
02181         {
02182           if ( minX > elemIt->sommets[ iNode ]->second.coord[ 0 ]) {
02183             minX = elemIt->sommets[ iNode ]->second.coord[ 0 ];
02184             iLeft = iNode;
02185           }
02186         }
02187         // indeces of the nodes neighboring the most left one
02188         int iPrev = ( iLeft - 1 < 0 ) ? nbNodes - 1 : iLeft - 1;
02189         int iNext = ( iLeft + 1 == nbNodes ) ? 0 : iLeft + 1;
02190         // find components of prev-left and left-next vectors
02191         double xP = elemIt->sommets[ iPrev ]->second.coord[ 0 ];
02192         double yP = elemIt->sommets[ iPrev ]->second.coord[ 1 ];
02193         double xN = elemIt->sommets[ iNext ]->second.coord[ 0 ];
02194         double yN = elemIt->sommets[ iNext ]->second.coord[ 1 ];
02195         double xL = elemIt->sommets[ iLeft ]->second.coord[ 0 ];
02196         double yL = elemIt->sommets[ iLeft ]->second.coord[ 1 ];
02197         double xPL = xL - xP, yPL = yL - yP; // components of prev-left vector
02198         double xLN = xN - xL, yLN = yN - yL; // components of left-next vector
02199         // normalise y of the vectors
02200         double modPL = sqrt ( xPL * xPL + yPL * yPL );
02201         double modLN = sqrt ( xLN * xLN + yLN * yLN );
02202         if ( modLN > DBL_MIN && modPL > DBL_MIN )
02203         {
02204           yPL /= modPL;
02205           yLN /= modLN;
02206           // summury direction of neighboring links must be positive
02207           bool clockwise = ( yPL + yLN > 0 );
02208           if ( !clockwise ) {
02209             if ( elemIt->geometricType != type ) {
02210               type = elemIt->geometricType;
02211               getReverseVector( type, swapVec );
02212             }
02213             reverse( *elemIt, swapVec );
02214           }
02215         }
02216       }
02217     }
02218   }
02219   else {
02220 
02221     // --------------------------------------
02222     // orient equally all connected 3D faces
02223     // --------------------------------------
02224     // connectivity of quadratic faces will be fixed by fixConnectivity()
02225     // in the next loop on elements
02226 
02227     // fill map of links and their faces
02228     set<const _maille*> faces;
02229     map<const _maille*, _groupe*> fgm;
02230     map<_link, list<const _maille*> > linkFacesMap;
02231     map<_link, list<const _maille*> >::iterator lfIt, lfIt2;
02232 
02233     medi.treatGroupes(); // erase groupes that wont be converted
02234     for (unsigned int i=0; i!=medi.groupes.size(); ++i)
02235     {
02236       _groupe& grp = medi.groupes[i];
02237       _groupe::TMailleIter maIt=grp.mailles.begin();
02238       if ( maIt==grp.mailles.end() || (*maIt)->dimensionWithPoly() != 2 )
02239         continue;
02240       for(; maIt!=grp.mailles.end(); ++maIt) {
02241         if ( faces.insert( &(**maIt )).second ) {
02242           for ( int j = 0; j < (int)(*maIt)->sommets.size(); ++j )
02243             linkFacesMap[ (*maIt)->link( j ) ].push_back( &(**maIt) );
02244           fgm.insert( make_pair( &(**maIt), &grp ));
02245         }
02246       }
02247     }
02248     // dump linkFacesMap
02249 //     for ( lfIt = linkFacesMap.begin(); lfIt!=linkFacesMap.end(); lfIt++) {
02250 //       cout<< "LINK: " << lfIt->first.first << "-" << lfIt->first.second << endl;
02251 //       list<const _maille*> & fList = lfIt->second;
02252 //       list<const _maille*>::iterator fIt = fList.begin();
02253 //       for ( ; fIt != fList.end(); fIt++ )
02254 //         cout << "\t" << **fIt << fgm[*fIt]->nom << endl;
02255 //     }
02256 
02257     // Each oriented link must appear in one face only, else a face is reversed.
02258 
02259     queue<const _maille*> faceQueue; // the queue contains well oriented faces
02260     // whose neighbors orientation is to be checked
02261 
02262     bool manifold = true;
02263     while ( !linkFacesMap.empty() )
02264     {
02265       if ( faceQueue.empty() ) {
02266         ASSERT_MED( !linkFacesMap.begin()->second.empty() );
02267         faceQueue.push( linkFacesMap.begin()->second.front() );
02268       }
02269       while ( !faceQueue.empty() )
02270       {
02271         const _maille* face = faceQueue.front();
02272         faceQueue.pop();
02273 
02274         // loop on links of <face>
02275         for ( int i = 0; i < (int)face->sommets.size(); ++i ) {
02276           _link link = face->link( i );
02277           // find the neighbor faces
02278           lfIt = linkFacesMap.find( link );
02279           int nbFaceByLink = 0;
02280           list< const _maille* > ml;
02281           if ( lfIt != linkFacesMap.end() )
02282           {
02283             list<const _maille*> & fList = lfIt->second;
02284             list<const _maille*>::iterator fIt = fList.begin();
02285             ASSERT_MED( fIt != fList.end() );
02286             for ( ; fIt != fList.end(); fIt++, nbFaceByLink++ ) {
02287               ml.push_back( *fIt );
02288               if ( *fIt != face ) // wrongly oriented neighbor face
02289               {
02290                 const _maille* badFace = *fIt;
02291                 // reverse and remove badFace from linkFacesMap
02292                 for ( int j = 0; j < (int)badFace->sommets.size(); ++j ) {
02293                   _link badlink = badFace->link( j );
02294                   if ( badlink == link ) continue;
02295                   lfIt2 = linkFacesMap.find( badlink );
02296                   if ( lfIt2 != linkFacesMap.end() ) {
02297                     list<const _maille*> & ff = lfIt2->second;
02298                     ff.erase( find( ff.begin(), ff.end(), badFace ));
02299                         if ( ff.empty() )
02300                           linkFacesMap.erase( lfIt2 );
02301                   }
02302                 }
02303                 badFace->reverse = true; // reverse
02304                 //INFOS_MED( "REVERSE " << *badFace );
02305                 faceQueue.push( badFace );
02306               }
02307             }
02308             linkFacesMap.erase( lfIt );
02309           }
02310           // add good neighbors to the queue
02311           _link revLink( link.second, link.first );
02312           lfIt = linkFacesMap.find( revLink );
02313           if ( lfIt != linkFacesMap.end() )
02314           {
02315             list<const _maille*> & fList = lfIt->second;
02316             list<const _maille*>::iterator fIt = fList.begin();
02317             for ( ; fIt != fList.end(); fIt++, nbFaceByLink++ ) {
02318               ml.push_back( *fIt );
02319               if ( *fIt != face )
02320                 faceQueue.push( *fIt );
02321             }
02322             linkFacesMap.erase( lfIt );
02323           }
02324           if ( nbFaceByLink > 2 ) {
02325             if ( manifold ) {
02326               list<const _maille*>::iterator i = ml.begin();
02327               INFOS_MED(nbFaceByLink << " faces by 1 link:");
02328               for( ; i!= ml.end(); i++ ) {
02329                 INFOS_MED("in object " << fgm[ *i ]->nom);
02330                 INFOS_MED( **i );
02331               }
02332             }
02333             manifold = false;
02334           }
02335         } // loop on links of the being checked face
02336       } // loop on the face queue
02337     } // while ( !linkFacesMap.empty() )
02338 
02339     if ( !manifold )
02340       INFOS_MED(" -> Non manifold mesh, faces orientation may be incorrect");
02341 
02342 
02343     // ---------------------------------------------------
02344     // fix connectivity of quadratic elements
02345     // ---------------------------------------------------
02346 
02347     for ( int dim = 1; dim <= 3; ++dim )
02348     {
02349       _maillageByDimIterator mailIt( medi, dim );
02350       while ( const set<_maille > * elems = mailIt.nextType() )
02351       {
02352         isQuadratic = getGibi2MedConnectivity( mailIt.type() );
02353         elemIt = elems->begin(), elemEnd = elems->end();
02354         for ( ; elemIt != elemEnd; elemIt++ )
02355         {
02356           // GIBI connectivity -> MED one
02357           if ( isQuadratic )
02358             fixConnectivity( *elemIt );
02359 
02360           // reverse quadratic faces
02361           if ( elemIt->reverse ) {
02362             if ( elemIt->geometricType != type ) {
02363               type = elemIt->geometricType;
02364               getReverseVector( type, swapVec );
02365             }
02366             reverse ( *elemIt, swapVec );
02367           }
02368         }
02369       }
02370     }
02371 
02372     // ---------------------------------------------------
02373     // Orient volumes according to MED conventions:
02374     // normal of a bottom (first) face should be downward
02375     // ---------------------------------------------------
02376 
02377     _maillageByDimIterator mailIt( medi, 3 );
02378     while ( const set<_maille > * elems = mailIt.nextType() )
02379     {
02380       elemIt = elems->begin(), elemEnd = elems->end();
02381       int nbBottomNodes = 0;
02382       switch ( elemIt->geometricType ) {
02383       case MED_TETRA4:
02384       case MED_TETRA10:
02385       case MED_PENTA6:
02386       case MED_PENTA15:
02387         nbBottomNodes = 3; break;
02388       case MED_PYRA5:
02389       case MED_PYRA13:
02390       case MED_HEXA8:
02391       case MED_HEXA20:
02392         nbBottomNodes = 4; break;
02393       default: continue;
02394       }
02395       getReverseVector( elemIt->geometricType, swapVec );
02396 
02397       for ( ; elemIt != elemEnd; elemIt++ )
02398       {
02399         // find a normal to the bottom face
02400         const _noeud* n[4] = {
02401           &elemIt->sommets[0]->second, // 3 bottom nodes
02402           &elemIt->sommets[1]->second,
02403           &elemIt->sommets[2]->second,
02404           &elemIt->sommets[nbBottomNodes]->second };// a top node
02405         double vec01 [3] = { // vector n[0]-n[1]
02406           n[1]->coord[0] - n[0]->coord[0],
02407           n[1]->coord[1] - n[0]->coord[1],
02408           n[1]->coord[2] - n[0]->coord[2], };
02409         double vec02 [3] = { // vector n[0]-n[2]
02410           n[2]->coord[0] - n[0]->coord[0],
02411           n[2]->coord[1] - n[0]->coord[1],
02412           n[2]->coord[2] - n[0]->coord[2] };
02413         double normal [3] = { // vec01 ^ vec02
02414           vec01[1] * vec02[2] - vec01[2] * vec02[1],
02415           vec01[2] * vec02[0] - vec01[0] * vec02[2],
02416           vec01[0] * vec02[1] - vec01[1] * vec02[0] };
02417         // check if the 102 angle is convex
02418         if ( nbBottomNodes > 3 ) {
02419           const _noeud* n3 = &elemIt->sommets[nbBottomNodes-1]->second;// last bottom node
02420           double vec03 [3] = { // vector n[0]-n3
02421             n3->coord[0] - n[0]->coord[0],
02422             n3->coord[1] - n[0]->coord[1],
02423             n3->coord[2] - n[0]->coord[2], };
02424           if ( fabs( normal[0]+normal[1]+normal[2] ) <= DBL_MIN ) { // vec01 || vec02
02425             normal[0] = vec01[1] * vec03[2] - vec01[2] * vec03[1]; // vec01 ^ vec03
02426             normal[1] = vec01[2] * vec03[0] - vec01[0] * vec03[2];
02427             normal[2] = vec01[0] * vec03[1] - vec01[1] * vec03[0];
02428           }
02429           else {
02430             double vec [3] = { // normal ^ vec01
02431               normal[1] * vec01[2] - normal[2] * vec01[1],
02432               normal[2] * vec01[0] - normal[0] * vec01[2],
02433               normal[0] * vec01[1] - normal[1] * vec01[0] };
02434             double dot2 = vec[0]*vec03[0] + vec[1]*vec03[1] + vec[2]*vec03[2]; // vec*vec03
02435             if ( dot2 < 0 ) { // concave -> reverse normal
02436               normal[0] *= -1;
02437               normal[1] *= -1;
02438               normal[2] *= -1;
02439             }
02440           }
02441         }
02442         // direction from top to bottom
02443         double tbDir[3];
02444         tbDir[0] = n[0]->coord[0] - n[3]->coord[0];
02445         tbDir[1] = n[0]->coord[1] - n[3]->coord[1];
02446         tbDir[2] = n[0]->coord[2] - n[3]->coord[2];
02447         // compare 2 directions: normal and top-bottom
02448         double dot = normal[0]*tbDir[0] + normal[1]*tbDir[1] + normal[2]*tbDir[2];
02449         if ( dot < 0. ) // need reverse
02450         {
02451           reverse( *elemIt, swapVec );
02452         }
02453       } // loop on volumes of one geometry
02454     } // loop on 3D geometry types
02455 
02456   } // space dimension == 3
02457 }
02458 
02459 //=======================================================================
02460 //function : fillMesh
02461 //purpose  : load data from medi to mesh
02462 //=======================================================================
02463 
02464 void GIBI_MESH_RDONLY_DRIVER::fillMesh(_intermediateMED* _ptrMedi)
02465 {
02466   const char* LOC = "GIBI_MESH_RDONLY_DRIVER::fillMesh(_intermediateMED* _ptrMedi) : ";
02467   BEGIN_OF_MED(LOC);
02468 
02469   MESH* mesh = (MESH*)_mesh;
02470   mesh->_name = _meshName;
02471 
02472   if (_ptrMedi)
02473   {
02474     if (!_maillageByDimIterator(*_ptrMedi).nextType() ||
02475         _ptrMedi->groupes.empty() ||
02476         _ptrMedi->points.empty()) {
02477       INFOS_MED(" Error while reading file: the data read are not completed " );
02478       return;
02479     }
02480     // fix element orientation
02481     orientElements( *_ptrMedi );
02482 
02483     mesh->_spaceDimension = _ptrMedi->points.begin()->second.coord.size();
02484     mesh->_numberOfNodes  = _ptrMedi->points.size();
02485     mesh->_coordinate     = _ptrMedi->getCoordinate();
02486 
02487     //Construction des groupes
02488     _ptrMedi->getGroups(mesh->_groupCell,
02489                         mesh->_groupFace,
02490                         mesh->_groupEdge,
02491                         mesh->_groupNode, mesh);
02492 
02493     mesh->_connectivity = _ptrMedi->getConnectivity();
02494   }
02495   END_OF_MED(LOC);
02496 }
02497 
02498 //================================================================================
02502 //================================================================================
02503 
02504 void GIBI_MESH_RDONLY_DRIVER::updateSupports()
02505 {
02506   _mesh->createFamilies();
02507 
02508   // add attributes to families
02509   set<string> famNames;
02510   for (medEntityMesh entity=MED_CELL; entity<MED_ALL_ENTITIES; ++entity)
02511   {
02512     int i, nb = _mesh->getNumberOfFamilies(entity);
02513     for ( i = 1; i <= nb; ++i ) {
02514       FAMILY* f = const_cast<FAMILY*>( _mesh->getFamily( entity, i ));
02515       f->setNumberOfAttributes( 1 );
02516       int* attIDs = new int[1];
02517       attIDs[0] = 1;
02518       f->setAttributesIdentifiers( attIDs );
02519       int* attVals = new int[1];
02520       attVals[0] = 1;
02521       f->setAttributesValues( attVals );
02522       string* attDescr = new string[1];
02523       attDescr[0] = "med_family";
02524       f->setAttributesDescriptions( attDescr );
02525       delete [] attDescr;
02526       // limit a name length
02527       if ( f->getName().length() > 31 ) {
02528         ostringstream name;
02529         name << "FAM" << f->getIdentifier();
02530         f->setName( name.str());
02531       }
02532       // check if family is on the whole mesh entity
02533       if (_mesh->getNumberOfElements( entity, MED_ALL_ELEMENTS ) ==
02534           f->getNumberOfElements( MED_ALL_ELEMENTS ))
02535         f->setAll( true );
02536     }
02537     // setAll() for groups
02538     nb = _mesh->getNumberOfGroups(entity);
02539     for ( i = 1; i <= nb; ++i ) {
02540       GROUP * g = const_cast<GROUP*>( _mesh->getGroup( entity, i ));
02541       if (_mesh->getNumberOfElements( entity, MED_ALL_ELEMENTS ) ==
02542           g->getNumberOfElements( MED_ALL_ELEMENTS ))
02543         g->setAll( true );
02544     }
02545   }
02546 }
02547 
02548 void GIBI_MESH_RDONLY_DRIVER::write( void ) const
02549   throw (MEDEXCEPTION)
02550 {
02551   throw MEDEXCEPTION("GIBI_MESH_RDONLY_DRIVER::write : Can't write with a RDONLY driver !");
02552 }
02553 
02554 
02555 /*--------------------- WRONLY PART -------------------------------*/
02556 
02557 GIBI_MESH_WRONLY_DRIVER::GIBI_MESH_WRONLY_DRIVER():GIBI_MESH_DRIVER()
02558 {
02559 }
02560 GIBI_MESH_WRONLY_DRIVER::GIBI_MESH_WRONLY_DRIVER(const string & fileName,
02561                                                  GMESH *        ptrMesh):
02562   GIBI_MESH_DRIVER(fileName,ptrMesh,WRONLY)
02563 {
02564   MESSAGE_MED("GIBI_MESH_WRONLY_DRIVER::GIBI_MESH_WRONLY_DRIVER(const string & fileName, MESH * ptrMesh) has been created");
02565 }
02566 GIBI_MESH_WRONLY_DRIVER::GIBI_MESH_WRONLY_DRIVER(const GIBI_MESH_WRONLY_DRIVER & driver):
02567   GIBI_MESH_DRIVER(driver)
02568 {
02569 }
02570 GIBI_MESH_WRONLY_DRIVER::~GIBI_MESH_WRONLY_DRIVER()
02571 {
02572   //MESSAGE_MED("GIBI_MESH_WRONLY_DRIVER::GIBI_MESH_WRONLY_DRIVER(const string & fileName, MESH * ptrMesh) has been destroyed");
02573 }
02574 GENDRIVER * GIBI_MESH_WRONLY_DRIVER::copy(void) const
02575 {
02576   return new GIBI_MESH_WRONLY_DRIVER(*this);
02577 }
02578 void GIBI_MESH_WRONLY_DRIVER::read (void)
02579   throw (MEDEXCEPTION)
02580 {
02581   throw MEDEXCEPTION("GIBI_MESH_WRONLY_DRIVER::read : Can't read with a WRONLY driver !");
02582 }
02583 
02584 //=======================================================================
02585 //function : open
02586 //purpose  :
02587 //=======================================================================
02588 
02589 void GIBI_MESH_WRONLY_DRIVER::open()
02590   //     throw (MEDEXCEPTION)
02591 {
02592   if( _status == MED_OPENED )
02593     return;
02594 
02595   const char * LOC = "GIBI_MESH_DRIVER::open()";
02596   BEGIN_OF_MED(LOC);
02597 
02598   MED_EN::med_mode_acces aMode = getAccessMode();
02599   switch (aMode) {
02600   case MED_EN::RDWR:
02601   case MED_EN::WRONLY: // should never append !!
02602     _gibi.open(_fileName.c_str(), ios::out);
02603     break;
02604   default:
02605     throw MEDEXCEPTION(LOCALIZED(STRING(LOC) << "Bad file mode access ! " << aMode));
02606   }
02607   //change for windows compilation
02608   if ( !_gibi ||
02609 #ifdef WNT
02610       !_gibi.is_open()
02611 #else
02612       !_gibi.rdbuf()->is_open()
02613 #endif
02614       )
02615   {
02616     _status = MED_CLOSED;
02617     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<" Could not open file "<<_fileName));
02618   }
02619   else
02620   {
02621     _status = MED_OPENED;
02622   }
02623   END_OF_MED(LOC);
02624 }
02625 
02626 //=======================================================================
02627 //function : close
02628 //purpose  :
02629 //=======================================================================
02630 
02631 void GIBI_MESH_WRONLY_DRIVER::close()
02632   //  throw (MEDEXCEPTION)
02633 {
02634   const char* LOC = "GIBI_MESH_DRIVER::close() ";
02635   BEGIN_OF_MED(LOC);
02636     if ( _status == MED_OPENED)
02637     {
02638         _gibi.close();
02639         _status = MED_CLOSED;
02640     }
02641   END_OF_MED(LOC);
02642 }
02643 
02644 //=======================================================================
02645 //function : write
02646 //purpose  :
02647 //=======================================================================
02648 
02649 void GIBI_MESH_WRONLY_DRIVER::write(void) const
02650   throw (MEDEXCEPTION)
02651 {
02652   const char* LOC = "void GIBI_MESH_WRONLY_DRIVER::write(void) const : ";
02653   BEGIN_OF_MED(LOC);
02654 
02655   // we are going to modify the _gibi field
02656   GIBI_MESH_WRONLY_DRIVER * me = const_cast<GIBI_MESH_WRONLY_DRIVER *>(this);
02657 //  try {
02658     // IMP 0020434: mapping GIBI names to MED names
02659     list<nameGIBItoMED> listGIBItoMED_mail;
02660     list<nameGIBItoMED> listGIBItoMED_cham;
02661     list<nameGIBItoMED> listGIBItoMED_comp;
02662     me->writeSupportsAndMesh(listGIBItoMED_mail);
02663     me->writeMEDNames(listGIBItoMED_mail, listGIBItoMED_cham, listGIBItoMED_comp);
02664     me->writeLastRecord();
02665 //   }
02666 //   catch (MEDEXCEPTION &ex)
02667 //   {
02668 //     INFOS_MED( ex.what() );
02669 //   }
02670 
02671   END_OF_MED(LOC);
02672 }
02673 
02674 //=======================================================================
02675 //function : getName
02676 //purpose  : return cleaned up support name
02677 //=======================================================================
02678 
02679 static string cleanName( const string& theName )
02680 {
02681   string name = theName;
02682   if ( !name.empty() ) {
02683     /*
02684     // find a name string end
02685     int i, len = name.length();
02686     for ( i = 0; i < len; ++i ) {
02687       if ( name[i] == 0 )
02688         break;
02689     }
02690     // cut off trailing white spaces
02691     while ( i > 0 && name[i-1] == ' ' )
02692       i--;
02693     if ( i != len ) {
02694       name = name.substr( 0, i );
02695       len = i;
02696     }
02697     */
02698     // cut off leading white spaces
02699     string::size_type firstChar = name.find_first_not_of(" \t");
02700     if (firstChar < name.length())
02701     {
02702       name = name.substr(firstChar);
02703     }
02704     else
02705     {
02706       name = ""; // only whitespaces there - remove them
02707     }
02708     // cut off trailing white spaces
02709     string::size_type lastChar = name.find_last_not_of(" \t");
02710     if (lastChar < name.length()) {
02711       name = name.substr(0, lastChar + 1);
02712     }
02713   }
02714   return name;
02715 }
02716 
02717 //=======================================================================
02718 //function : addSupport
02719 //purpose  :
02720 //=======================================================================
02721 
02722 bool GIBI_MESH_WRONLY_DRIVER::addSupport( const SUPPORT * support )
02723 {
02724   if ( !support )
02725     return false;
02726   map<const SUPPORT*,supportData>::iterator su = _supports.find( support );
02727   if ( su != _supports.end() )
02728     return ( su->second.getNumberOfTypes() > 0 );
02729 
02730   if ( support->getMesh() != _mesh )
02731     throw MEDEXCEPTION(LOCALIZED(STRING("cant write support of other mesh" )));
02732 
02733   MESH* mesh = (MESH*)_mesh;
02734 
02735   // get sub-supports and define a support type name
02736   string supType;
02737   list<const SUPPORT*> sList;
02738   const GROUP* group = dynamic_cast< const GROUP* >(support);
02739   if ( group )
02740   {
02741     if ( group->getNumberOfTypes() > 0 || group->isOnAllElements() )
02742       sList.push_back( group );
02743     else {
02744       int iFam, nbFam = group->getNumberOfFamilies();
02745       for ( iFam = 1; iFam <= nbFam; ++iFam )
02746         sList.push_back( group->getFamily( iFam ));
02747     }
02748     supType = "group";
02749   }
02750   else
02751   {
02752     sList.push_back( support );
02753     supType = dynamic_cast< const FAMILY* >(support) ? "family" : "support";
02754   }
02755 
02756   supportData & data = _supports[ support ];
02757   data._cleanName = cleanName( support->getName() );
02758 
02759   // check if it is a writtable support, i.e.
02760   // nodal connectivity for a support entity exists
02761   medEntityMesh entity = support->getEntity();
02762   if ( entity != MED_NODE && !mesh->existConnectivity( MED_NODAL, entity )) {
02763     INFOS_MED("Do not save " << supType << " of entity " << entity
02764           << " named <" << data._cleanName << "> nodal connectivity not defined");
02765     return false;
02766   }
02767 
02768   // fill supportData
02769   list<const SUPPORT*>::iterator sIt = sList.begin();
02770   for ( ; sIt != sList.end(); sIt++ )
02771   {
02772     bool onAll = (*sIt)->isOnAllElements();
02773     int nbTypes = 0;
02774     if ( !onAll )
02775       nbTypes = (*sIt)->getNumberOfTypes();
02776     else
02777       nbTypes = _mesh->getNumberOfTypes( entity );
02778     if ( nbTypes == 0 )
02779       continue;
02780     const medGeometryElement* types = 0;
02781     if ( !onAll )
02782       types = (*sIt)->getTypes();
02783     else if ( entity != MED_NODE )
02784       types = _mesh->getTypes( entity );
02785     for ( int iType = 0; iType < nbTypes; ++iType )
02786     {
02787       if ( types && types[ iType ] > MED_HEXA20 )
02788         continue; // poly
02789       medGeometryElement geomType = types ? types[ iType ] : MED_ALL_ELEMENTS;
02790       const int * ptrElemIDs = 0;
02791       int elemID1 = 0, nbElems = 0;
02792       if ( onAll ) {
02793         nbElems = _mesh->getNumberOfElements( entity, geomType );
02794         elemID1 = (entity == MED_NODE) ? 1 : mesh->getGlobalNumberingIndex (entity)[ iType ];
02795       }
02796       else {
02797         nbElems = (*sIt)->getNumberOfElements( geomType );
02798         ptrElemIDs = (*sIt)->getNumber( geomType );
02799       }
02800       if ( geomType == 0 || ( entity == MED_NODE ))
02801         geomType = MED_POINT1;
02802 
02803       data.addTypeData( geomType, nbElems, ptrElemIDs, elemID1 );
02804     }
02805   }
02806 
02807   if ( data.getNumberOfTypes() == 0 ) {
02808     INFOS_MED("Do not save " << supType << " of entity " << entity
02809           << " named <" << data._cleanName << "> no geometric types");
02810     return false;
02811   }
02812 
02813   return true;
02814 }
02815 
02816 //=======================================================================
02817 //function : getSupportIndex
02818 //purpose  :
02819 //=======================================================================
02820 
02821 int GIBI_MESH_WRONLY_DRIVER::getSubMeshIdAndSize(const SUPPORT *        support,
02822                                                  list<pair<int,int> > & idsAndSizes) const
02823 {
02824   idsAndSizes.clear();
02825   map<const SUPPORT*,supportData>::const_iterator su = _supports.find( support );
02826   if ( su == _supports.end() )
02827     return 0;
02828 
02829   supportData * data = const_cast<supportData *>( & su->second );
02830   int id = data->_id;
02831   if ( data->getNumberObjects() > data->getNumberOfTypes() )
02832     id++;
02833   supportData::typeIterator tIt = data->_types.begin();
02834   for ( ; tIt != data->_types.end(); ++tIt )
02835   {
02836     int size = 0;
02837     list< typeData >& td = tIt->second;
02838     list< typeData >::iterator tdIt = td.begin();
02839     for ( ; tdIt != td.end(); ++tdIt )
02840       size += tdIt->_nbElems;
02841     idsAndSizes.push_back( make_pair( id++, size ));
02842   }
02843   return idsAndSizes.size();
02844 }
02845 
02846 // ============================================================
02847 // the class writes endl to the file as soon as <limit> fields
02848 // have been written after the last endl
02849 // ============================================================
02850 
02851 class TFieldCounter
02852 {
02853   fstream& _file;
02854   int _count, _limit;
02855  public:
02856   TFieldCounter(fstream& f, int limit=0): _file(f), _limit(limit) { init(); }
02857   void init(int limit=0) // init, is done by stop() as well
02858   { if (limit) _limit = limit; _count = 0; }
02859   void operator++(int) // next
02860   { if ( ++_count == _limit ) { _file << endl; init(); }}
02861   void stop() // init() and write endl if there was no endl after the last written field
02862   { if ( _count ) _file << endl; init(); }
02863 };
02864 
02865 //=======================================================================
02866 //function : writeElements
02867 //purpose  : ptrElemIDs and elemID1 provide two alternative ways of giving
02868 //           elements to write.
02869 //           If elemSet != 0 then an element is
02870 //           ( addElemInSet ? <written and added to elemSet> : <ignored if id is in elemSet>)
02871 //=======================================================================
02872 
02873 void GIBI_MESH_WRONLY_DRIVER::writeElements (medGeometryElement geomType,
02874                                              list< typeData >&  typeDataList,
02875                                              const int *        nodalConnect,
02876                                              const int *        nodalConnectIndex)
02877 {
02878   // ITYPEL : type de l'鬩ment 1=point, 2=segment ?eux noeuds...
02879   // NBSOUS : nombre de sous parties dans cet objet,
02880   //          une sous partie par type d'鬩ments le composant.
02881   // NBREF : nombre de sous r馩rences. Une r馩rence est par exemple le contour
02882   // NBNOEL : nombre de noeuds par 鬩ment
02883   // NBEL : nombre d'鬩ments
02884 
02885   int castemType = GIBI_MESH_DRIVER::med2gibiGeom( geomType );
02886   const char* zeroI8 = "       0"; // FORMAT(I8)
02887   unsigned nbElemNodes = geomType % 100;
02888 
02889   // indices to transform MED connectivity to GIBI one
02890   vector< int > toGibiConn;
02891   toGibiConn.reserve( nbElemNodes );
02892   if ( const int * toMedConn = getGibi2MedConnectivity( geomType )) {
02893     toGibiConn.resize( nbElemNodes );
02894     for ( unsigned i = 0; i < nbElemNodes; ++i )
02895       toGibiConn[ toMedConn[ i ]] = i;
02896   }
02897   else {
02898     while ( toGibiConn.size() < nbElemNodes )
02899       toGibiConn.push_back( toGibiConn.size() );
02900   }
02901 
02902   // count total nb of elements
02903   int nbElements = 0;
02904   list< typeData >::iterator td = typeDataList.begin();
02905   for ( ; td != typeDataList.end(); td++ )
02906     nbElements += td->_nbElems;
02907 
02908   _gibi << setw(8) << castemType <<  // ITYPE
02909     zeroI8 <<                       // NBSOUS
02910       zeroI8 <<                     // NBREF
02911         setw(8) << nbElemNodes <<   // NBNOEL
02912           setw(8) << nbElements <<  // NBEL
02913             endl;
02914 
02915   MESSAGE_MED("writeElements(): geomType=" << geomType << " nbElements= " << nbElements)
02916 
02917   // L 'enregistrement donnant le num? de la couleur des 鬩ments.
02918   // * 8000 FORMAT(10I8)
02919   TFieldCounter fcount( _gibi, 10 );
02920   int iElem = 0;
02921   for ( ; iElem < nbElements; ++iElem, fcount++ )
02922     _gibi << zeroI8;
02923   fcount.stop();
02924 
02925   // Tableau des connectivit鳮 Description du premier 鬩ment puis du deuxi譥...
02926   // ATTENTION il ne s'agit pas de la num?tation vraie,
02927   // il faut la faire passer par le filtre du dernier tableau de la pile num? 32.
02928   //int nbSkipped = 0;
02929 
02930   for ( td = typeDataList.begin(); td != typeDataList.end(); td++ )
02931   {
02932     for ( int i = 0; i < td->_nbElems; i++ )
02933     {
02934       iElem = td->_ptrElemIDs ? td->_ptrElemIDs[ i ] : td->_elemID1 + i;
02935       if ( geomType == MED_POINT1 )
02936       {
02937         _gibi << setw(8) << iElem;
02938         fcount++;
02939       }
02940       else
02941       {
02942         int nodeId = nodalConnectIndex[ iElem - 1 ] - 1;
02943         for ( unsigned iNode = 0; iNode < nbElemNodes; ++iNode, fcount++ ) {
02944           _gibi << setw(8) << nodalConnect[ nodeId + toGibiConn[ iNode ]];
02945         }
02946       }
02947     }
02948   }
02949 
02950   fcount.stop();
02951 }
02952 
02953 //=======================================================================
02954 //function : addName
02955 //purpose  : make name uppercase and shorter than 9, add it to nameNbMap,
02956 //           raise if not unique
02957 //=======================================================================
02958 /*
02959 void GIBI_MESH_WRONLY_DRIVER::addName(map<string,int>& nameMap,
02960                                       string&          theName,
02961                                       int              index,
02962                                       string           prefix)
02963 {
02964   string name = cleanName( theName );
02965   if ( !name.empty() ) {
02966     int len = name.length();
02967 #ifdef THROW_ON_BAD_NAME
02968     if ( len > 8 )
02969       throw MEDEXCEPTION(STRING("Can't write name longer than 8: ") << name );
02970 
02971     for ( int i = 0; i < len; ++i )
02972       name[i] = toupper( name[i] );
02973     if ( ! nameMap.insert( make_pair( name, index )).second )
02974       throw MEDEXCEPTION(STRING("Can't write not unique name: ") << name );
02975 #else
02976     bool ok = ( len <= 8 && len > 0 );
02977     if ( ok ) {
02978       for ( int i = 0; i < len; ++i )
02979         name[i] = toupper( name[i] );
02980       ok = nameMap.insert( make_pair( name, index )).second;
02981     }
02982     if ( !ok ) {
02983       char *str=new char[ prefix.size() + 13 ];
02984       int j = 1;
02985       do {
02986         sprintf( str, "%s_%d", prefix.c_str(), nameMap.size()+j );
02987         ok = nameMap.insert( make_pair( str, index )).second;
02988         j++;
02989       } while ( !ok );
02990       INFOS_MED( "Save <" << name << "> as <" << str << ">");
02991       delete [] str;
02992     }
02993 #endif
02994   }
02995 }
02996 */
02997 
02998 // Converts names like:
02999 // MED:
03000 //   TEMPERATURE_FLUIDE
03001 //   TEMPERATURE_SOLIDE
03002 //   PRESSION
03003 //   NU
03004 //   VOLUM001
03005 //   VOLUMOFOBJECT
03006 //   VOLUM002
03007 //
03008 // GIBI:
03009 //   TEMPE001
03010 //   TEMPE002
03011 //   PRESSION
03012 //   NU
03013 //   VOLUM001
03014 //   VOLUM003
03015 //   VOLUM002
03016 void GIBI_MESH_WRONLY_DRIVER::addName (map<string,int>& nameMap,
03017                                        map<string,int>& namePrefixesMap,
03018                                        const string&    theName,
03019                                        int              index)
03020 {
03021   string name = cleanName(theName);
03022   int ind = index;
03023 
03024   if (!name.empty()) {
03025     int len = name.length();
03026     for (int i = 0; i < len; ++i)
03027       name[i] = toupper(name[i]);
03028 
03029     bool doResave = false; // only for tracing
03030 
03031     // I. Save a short name as it is
03032     if (len <= 8) {
03033       INFOS_MED("Save <" << theName << "> as <" << name << ">");
03034 
03035       map<string,int>::iterator it = nameMap.find(name);
03036       if (it != nameMap.end()) {
03037         // There is already such name in the map.
03038 
03039         // a. Replace in the map the old pair by the current one
03040         int old_ind = nameMap[name];
03041         nameMap[name] = ind;
03042         // b. Rebuild the old pair (which was in the map,
03043         //    it seems to be built automatically by step II)
03044         ind = old_ind;
03045         // continue with step II
03046         doResave = true; // only for tracing
03047       }
03048       else {
03049         // Save in the map
03050         nameMap.insert(make_pair(name, ind));
03051 
03052         // Update loc_index for this name (if last free characters represents a number)
03053         // to avoid conflicts with long names, same in first 5 characters
03054         if (len == 8) {
03055           int new_loc_index = atoi(name.c_str() + 5);
03056           if (new_loc_index > 0) {
03057             // prefix
03058             char str [6];
03059             strncpy(str, name.c_str(), 5);
03060             str[5] = '\0';
03061 
03062             if (namePrefixesMap.find(str) != namePrefixesMap.end()) {
03063               int old_loc_index = namePrefixesMap[str];
03064               if (new_loc_index < old_loc_index) new_loc_index = old_loc_index;
03065             }
03066             namePrefixesMap[str] = new_loc_index;
03067           }
03068         }
03069         return;
03070       }
03071     } // if (len <= 8)
03072 
03073     // II. Cut long name and add a numeric suffix
03074 
03075     // first 5 or less characters of the name
03076     if (len > 5) len = 5;
03077     char str [9];
03078     str[8] = '\0';
03079     int addr = 0;
03080     strncpy(str, name.c_str(), len);
03081     addr = len;
03082     str[addr] = '\0';
03083 
03084     // numeric suffix
03085     int loc_index = 1;
03086     if (namePrefixesMap.find(str) != namePrefixesMap.end())
03087       loc_index = namePrefixesMap[str] + 1;
03088     namePrefixesMap[str] = loc_index;
03089 
03090     if (loc_index > 999)
03091       throw MEDEXCEPTION(STRING("Can't write not unique name: ") << name);
03092 
03093     if (loc_index < 100) {
03094       str[addr] = '0';
03095       addr++;
03096     }
03097     if (loc_index < 10) {
03098       str[addr] = '0';
03099       addr++;
03100     }
03101     sprintf(str + addr, "%d", loc_index);
03102 
03103     nameMap.insert(make_pair(str, ind));
03104     if (doResave) {
03105       INFOS_MED("Resave previous <" << name << "> as <" << str << ">");
03106     }
03107     else {
03108       INFOS_MED("Save <" << theName << "> as <" << str << ">");
03109     }
03110   }
03111 }
03112 
03113 //=======================================================================
03114 //function : writeNames
03115 //purpose  :
03116 //=======================================================================
03117 
03118 void GIBI_MESH_WRONLY_DRIVER::writeNames( map<string,int>& nameNbMap )
03119 {
03120   // La pile num? 1 est celle des objets de type maillage.
03121   // La ligne suivante donne le nom des objets maillages sauv鳮
03122   // * 8001       FORMAT(8(1X,A8))
03123   if ( !nameNbMap.empty() )
03124   {
03125     TFieldCounter fcount( _gibi, 8 );
03126     _gibi << left;
03127     map<string,int>::iterator nameNbIt = nameNbMap.begin();
03128     for ( ; nameNbIt != nameNbMap.end(); nameNbIt++, fcount++ ) {
03129       _gibi << " " << setw(8) << nameNbIt->first;
03130     }
03131     fcount.stop();
03132     _gibi << right;
03133     // La ligne suivante donne les num?s d'ordre, dans la pile,
03134     // des objets nomm?cit?pr飩demment.
03135     // *  8000 FORMAT(10I8)
03136     nameNbIt = nameNbMap.begin();
03137     for ( fcount.init(10); nameNbIt != nameNbMap.end(); nameNbIt++, fcount++ )
03138       _gibi << setw(8) << nameNbIt->second;
03139     fcount.stop();
03140   }
03141 }
03142 
03143 //=======================================================================
03144 //function : writeSupportsAndMesh
03145 //purpose  :
03146 //=======================================================================
03147 
03148 void GIBI_MESH_WRONLY_DRIVER::writeSupportsAndMesh(list<nameGIBItoMED>& listGIBItoMED_mail)
03149 {
03150   const char * LOC = "void GIBI_MESH_WRONLY_DRIVER::writeSupportsAndMesh() ";
03151   BEGIN_OF_MED(LOC);
03152 
03153   if (_status!=MED_OPENED)
03154     throw MEDEXCEPTION(LOCALIZED(STRING(LOC) << "file " << _fileName<<  " is not opened." ));
03155   if (!_mesh)
03156     throw MEDEXCEPTION(LOCALIZED(STRING(LOC) << "can't write a NULL mesh" ));
03157 
03158   const MESH* mesh = _mesh->convertInMESH();
03159   AutoDeref meshDeref( mesh );
03160 
03161   if (!mesh->getConnectivityptr()) 
03162     throw MEDEXCEPTION(LOCALIZED(STRING(LOC) << "can't write a mesh with NULL connectivity" ));
03163 
03164   // fill _supports with families and groups
03165   medEntityMesh entity;
03166   for (entity=MED_CELL; entity<MED_ALL_ENTITIES; ++entity)
03167   {
03168     int i, nb = _mesh->getNumberOfGroups(entity);
03169     for ( i = 1; i <= nb; ++i )
03170       addSupport( _mesh->getGroup( entity, i ));
03171 //     nb = _mesh->getNumberOfFamilies(entity);
03172 //     for ( i = 1; i <= nb; ++i )
03173 //       addSupport( _mesh->getFamily( entity, i ));
03174   }
03175 
03176   // --------------------------------------------------------------------
03177   // Count total nb of objects: an object per an element type in support
03178   // plus an object per an element type not used in _supports.
03179   // Collect object names
03180   // --------------------------------------------------------------------
03181 
03182   vector<int> nbSuppElemsByType(MED_HEXA20+1,0);
03183   map<string,int> nameNbMap;
03184   map<string,int> namePrefixMap;
03185   map<const SUPPORT*,supportData>::iterator supIt = _supports.begin();
03186   int i, nb_objects = 0;
03187   for ( ; supIt != _supports.end(); supIt++ )
03188   {
03189     supportData & data = supIt->second;
03190     int nbSupObj = data.getNumberObjects();
03191     if ( nbSupObj == 0 )
03192       continue;
03193     data._id = nb_objects + 1;
03194     nb_objects += nbSupObj;
03195 
03196     //addName( nameNbMap, data._cleanName, data._id, "C" );
03197     addName(nameNbMap, namePrefixMap, data._cleanName, data._id);
03198 
03199     // IMP 0020434: mapping GIBI names to MED names
03200     nameGIBItoMED aMEDName;
03201     aMEDName.gibi_pile = PILE_SOUS_MAILLAGE;
03202     aMEDName.gibi_id = data._id;
03203     aMEDName.med_name = data._cleanName;
03204     listGIBItoMED_mail.push_back(aMEDName);
03205 
03206     MESSAGE_MED( "obj " << data._id << " " << data._cleanName);
03207 
03208     // count elements: take into account supports on all elements and families only
03209     const SUPPORT* support = supIt->first;
03210     if ( support->isOnAllElements() || dynamic_cast< const FAMILY* >( support ))
03211     {
03212       supportData::typeIterator tIt = data._types.begin();
03213       for ( ; tIt != data._types.end(); ++tIt )
03214         if ( support->isOnAllElements() )
03215         {
03216           nbSuppElemsByType[ tIt->first ] = INT_MAX / 100;
03217         }
03218         else
03219         {
03220           list< typeData >& td = tIt->second;
03221           list< typeData >::iterator tdIt = td.begin();
03222           for ( ; tdIt != td.end(); ++tdIt )
03223             nbSuppElemsByType[ tIt->first] += tdIt->_nbElems;
03224         }
03225     }
03226   }
03227 
03228   // count types of mesh elements that are not all in _supports
03229   int iType, nbTypes;
03230   entity = mesh->getConnectivityptr()->getEntity();
03231   for ( ; entity < MED_NODE; entity++ )
03232   {
03233     nbTypes = _mesh->getNumberOfTypes( entity );
03234     if ( nbTypes == 0 || !mesh->existConnectivity( MED_NODAL, entity ))
03235       continue;
03236     const medGeometryElement* types = _mesh->getTypes( entity );
03237     for ( iType = 0; iType < nbTypes; ++iType )
03238     {
03239       int nbElemInSups = nbSuppElemsByType[ types[ iType ]];
03240       int nbElemInMesh = _mesh->getNumberOfElements(entity, types[ iType ]);
03241       if ( nbElemInSups < nbElemInMesh ) {
03242         nb_objects++;
03243         nbSuppElemsByType[ types[ iType ]] = -1; // to keep written elements of _supports
03244       }
03245     }
03246   }
03247 
03248   // ------------
03249   // Write file
03250   // ------------
03251 
03252   // Premier paquet dont le nombre de lignes ne varie pas.
03253   // On y trouve des indications g鮩rales.
03254   const int dim = _mesh->getSpaceDimension();
03255   _gibi << " ENREGISTREMENT DE TYPE   4" << endl;
03256   _gibi << " NIVEAU  15 NIVEAU ERREUR   0 DIMENSION   " << dim <<endl;
03257   _gibi << " DENSITE  .00000E+00" << endl;
03258   _gibi << " ENREGISTREMENT DE TYPE   7" << endl;
03259   _gibi << " NOMBRE INFO CASTEM2000   8" <<endl;
03260   _gibi << " IFOUR  -1 NIFOUR   0 IFOMOD  -1 IECHO   1 IIMPI   0 IOSPI   0 ISOTYP   1" << endl;
03261   _gibi << " NSDPGE     0" << endl;
03262 
03263   // Deuxi譥 paquet qui d馩nit toutes les piles
03264   // (une pile par type d'objet et certaines piles en plus).
03265   // Un enregistrement de type 2 pr鶩ent de l'飲iture d'une nouvelle pile,
03266   // celui de type 5 pr鶩ent de la fin.
03267   // * 800   FORMAT (' ENREGISTREMENT DE TYPE', I4)
03268   _gibi << " ENREGISTREMENT DE TYPE   2" << endl;
03269   // * 801     FORMAT(' PILE NUMERO',I4,'NBRE OBJETS NOMMES',I8,'NBRE OBJETS',I8)
03270   _gibi << " PILE NUMERO   1NBRE OBJETS NOMMES" << setw(8) << nameNbMap.size() <<
03271     "NBRE OBJETS" << setw(8) << nb_objects <<endl;
03272 
03273   writeNames( nameNbMap );
03274 
03275   // Passage ?a description des objets les uns apr賠les autres.
03276   // Le premier enregistrement de chaque objet est compos頤e 5 nombres repr鳥ntant :
03277   // ITYPEL : type de l'鬩ment 1=point, 2=segment ?eux noeuds...
03278   // NBSOUS : nombre de sous parties dans cet objet,
03279   //          une sous partie par type d'鬩ments le composant.
03280   // NBREF : nombre de sous r馩rences. Une r馩rence est par exemple le contour
03281   // NBNOEL : nombre de noeuds par 鬩ment
03282   // NBEL : nombre d'鬩ments
03283   // Si ITYPEL=0 alors NBSOUS diff鲥nt de z?. Dans ce cas on lira la liste des positions,
03284   // dans la pile des objets, des sous parties le composant.
03285   // Si NBSOUS=0, NBNOEL et NBEL sont diff鲥nts de z?, on trouve, au besoin,
03286   // la liste des r馩rences , les num?s des couleurs puis les connectivit鳮
03287 
03288   TFieldCounter fcount( _gibi, 10 );
03289   const char* zeroI8 = "       0"; // FORMAT(I8)
03290   for ( supIt = _supports.begin(); supIt != _supports.end(); supIt++ )
03291   {
03292     supportData & data = supIt->second;
03293     int nbSupObj = data.getNumberObjects();
03294     if ( nbSupObj == 0 )
03295       continue;
03296     MESSAGE_MED("support " << data._id << "<" << data._cleanName << ">");
03297 
03298     // write a compound object
03299     int nbTypes = data.getNumberOfTypes();
03300     if ( nbSupObj > nbTypes )
03301     {
03302       _gibi << zeroI8 << setw(8) << nbTypes << zeroI8 << zeroI8 << zeroI8 << endl;
03303       for ( int i_sub = 1; i_sub <= nbTypes; ++i_sub, fcount++ )
03304         _gibi << setw(8) << ( data._id + i_sub );
03305       fcount.stop();
03306     }
03307 
03308     // write components
03309     entity = supIt->first->getEntity();
03310     const int * nodalConnect = 0, * nodalConnectIndex = 0;
03311     if ( entity != MED_NODE ) {
03312       nodalConnect = mesh->getConnectivity (MED_NODAL,entity,MED_ALL_ELEMENTS);
03313       nodalConnectIndex = mesh->getConnectivityIndex (MED_NODAL,entity);
03314     }
03315     supportData::typeIterator tIt = data._types.begin();
03316     for ( ; tIt != data._types.end(); ++tIt )
03317     {
03318       writeElements (tIt->first,
03319                      tIt->second,
03320                      nodalConnect,
03321                      nodalConnectIndex);
03322     }
03323   }  // loop on _supports
03324 
03325   // Write elements that are not in _supports
03326 
03327   supportData data;
03328   entity = mesh->getConnectivityptr()->getEntity();
03329   for ( ; entity < MED_NODE; entity++ )
03330   {
03331     int nbTypes = _mesh->getNumberOfTypes( entity );
03332     if ( nbTypes == 0 || !mesh->existConnectivity( MED_NODAL, entity ))
03333       continue;
03334     const medGeometryElement* types = _mesh->getTypes( entity );
03335     const int * nbIndex = mesh->getGlobalNumberingIndex (entity);
03336     const int * nodalConnect = 0, * nodalConnectIndex = 0;
03337     nodalConnect = mesh->getConnectivity (MED_NODAL,entity,MED_ALL_ELEMENTS);
03338     nodalConnectIndex = mesh->getConnectivityIndex (MED_NODAL,entity);
03339 
03340     for ( int iType = 1; iType <= nbTypes; ++iType )
03341     {
03342       int nbElements = nbIndex[ iType ] - nbIndex[ iType - 1 ];
03343       medGeometryElement geomType = types[ iType - 1 ];
03344       if ( nbSuppElemsByType[ geomType ] >= nbElements )
03345         continue; // all elements are written with _supports
03346 
03347       int elemId1 = nbIndex[ iType - 1 ];
03348       data.addTypeData( geomType, nbElements, 0, elemId1 );
03349 
03350       writeElements (geomType,
03351                      data._types[ geomType ],
03352                      nodalConnect,
03353                      nodalConnectIndex);
03354     }
03355   }
03356 
03357   // D颵t de la pile 32 (celle des points)
03358 
03359   int nbNodes = _mesh->getNumberOfNodes();
03360   _gibi << " ENREGISTREMENT DE TYPE   2" << endl;
03361   _gibi << " PILE NUMERO  32NBRE OBJETS NOMMES       0" <<
03362     "NBRE OBJETS" << setw(8) << nbNodes << endl;
03363   // Liste des noms de points
03364   // * 8001       FORMAT(8(1X,A8))
03365   // No named nodes
03366   // suit le nombre de noeuds
03367   _gibi << setw(8) << nbNodes << endl;
03368   // Le tableau suivant donne le filtre pour avoir le vrai num? des noeuds
03369   // appartenant aux 鬩ments d飲its. Par exemple, si un 鬩ment, d飲it
03370   // dans la pile 1, fait r馩rence ?n num? de noeud 駡l ? il faut le
03371   // mettre 駡l ?2
03372   // * 8000 FORMAT(10I8)
03373   for ( i = 0; i < nbNodes; ++i, fcount++ )
03374     _gibi << setw(8) << i + 1;
03375   fcount.stop();
03376 
03377   // D颵t de pile 33 (celle des configurations (coordonn?))
03378   _gibi << " ENREGISTREMENT DE TYPE   2" << endl;
03379   _gibi << " PILE NUMERO  33NBRE OBJETS NOMMES       0NBRE OBJETS       1" << endl;
03380   // Suit le nombre de points dont on donne les coordonn?
03381   int nbValues = nbNodes * ( dim + 1 );
03382   _gibi << setw(8) << nbValues << endl;
03383   // Les coordonn? sont donn? par noeuds. D'abord le premier puis le deuxi譥...
03384   // Pour chaque noeuds, on donne les 2 ou 3 coordonn? plus la densit頣ourante
03385   // au moment de sa cr顴ion.
03386   // * 8003   FORMAT(1P,3E22.14)
03387   _gibi.precision(14);
03388   _gibi.setf( ios_base::scientific, ios_base::floatfield );
03389   _gibi.setf( ios_base::uppercase );
03390   const double * coords = mesh->getCoordinates(MED_FULL_INTERLACE);
03391   int j = 0;
03392   const double precision = 1.e-99; // PAL12077
03393   for ( fcount.init(3),i = 0; i < nbNodes; ++i, j += dim )
03394   {
03395     for ( int iCoord = 0; iCoord < dim; ++iCoord, fcount++ ) {
03396       double coo = coords[ j + iCoord ];
03397       bool  zero = ( -precision < coo && coo < precision );
03398       _gibi << setw(22) << ( zero ? 0.0 : coo );
03399     }
03400     _gibi << setw(22) << 0.0; // densite
03401     fcount++;
03402   }
03403   fcount.stop();
03404 
03405   END_OF_MED(LOC);
03406 }
03407 
03408 //=======================================================================
03409 //function : writeMEDNames
03410 //purpose  :
03411 //=======================================================================
03412 void GIBI_MESH_WRONLY_DRIVER::writeMEDNames (const list<nameGIBItoMED>& listGIBItoMED_mail,
03413                                              const list<nameGIBItoMED>& listGIBItoMED_cham,
03414                                              const list<nameGIBItoMED>& listGIBItoMED_comp)
03415 {
03416   // IMP 0020434: mapping GIBI names to MED names
03417   // Store correspondence between GIBI and MED names
03418   // as one PILE_STRINGS and one PILE_TABLES
03419   // (in three tables: MED_MAIL, MED_CHAM and MED_COMP)
03420 
03421   int nbNames_mail = listGIBItoMED_mail.size();
03422   int nbNames_cham = listGIBItoMED_cham.size();
03423   int nbNames_comp = listGIBItoMED_comp.size();
03424 
03425   int nbTables = 0;
03426   if (nbNames_mail) nbTables++;
03427   if (nbNames_cham) nbTables++;
03428   if (nbNames_comp) nbTables++;
03429 
03430   if (!nbTables)
03431     return;
03432 
03433   // The whole string (concatenated names)
03434   string theWholeString;
03435   list<int> theOffsets;
03436   int currOffset = 0;
03437 
03438   // The TABLE PILE
03439   // * 800   FORMAT (' ENREGISTREMENT DE TYPE', I4)
03440   _gibi << " ENREGISTREMENT DE TYPE   2" << endl;
03441   // * 801     FORMAT(' PILE NUMERO',I4,'NBRE OBJETS NOMMES',I8,'NBRE OBJETS',I8)
03442   _gibi << " PILE NUMERO  10NBRE OBJETS NOMMES" << setw(8) << nbTables <<
03443     "NBRE OBJETS" << setw(8) << nbTables << endl; // <nbTables> named tables
03444   // Table names
03445   if (nbNames_mail)
03446     _gibi << " MED_MAIL";
03447   if (nbNames_cham)
03448     _gibi << " MED_CHAM";
03449   if (nbNames_comp)
03450     _gibi << " MED_COMP";
03451   _gibi << endl;
03452   // Table indices
03453   _gibi << setw(8) << 1;
03454   if (nbTables > 1) _gibi << setw(8) << 2;
03455   if (nbTables > 2) _gibi << setw(8) << 3;
03456   _gibi << endl;
03457 
03458   int istr = 1;
03459 
03460   // Table MED_MAIL
03461   if (nbNames_mail) {
03462     // Provide unique MED names, to exclude conflicts on reading saved files
03463     // (use case: read fra.med, save it to GIBI, read it from GIBI,
03464     // save to MED again -> this new MED file is not readable)
03465     set<string> medUniqueNames;
03466 
03467     _gibi << setw(8) << nbNames_mail*4 << endl; // Nb of table values
03468 
03469     TFieldCounter fcount1 (_gibi, 10);
03470     _gibi << right;
03471     list<nameGIBItoMED>::const_iterator itGIBItoMED = listGIBItoMED_mail.begin();
03472     for (; itGIBItoMED != listGIBItoMED_mail.end(); itGIBItoMED++, istr++) {
03473       // PILE of i-th key(med name)
03474       _gibi << setw(8) << 27; fcount1++; // PILE_STRINGS number is 27
03475       // ID of i-th key(med name)
03476       _gibi << setw(8) << istr; fcount1++;
03477 
03478       // PILE of i-th value(gibi name)
03479       _gibi << setw(8) << itGIBItoMED->gibi_pile; fcount1++; // PILE_SOUS_MAILLAGE number is 1
03480       // ID of i-th value(gibi name)
03481       _gibi << setw(8) << itGIBItoMED->gibi_id; fcount1++;
03482 
03483       // check MED name to be unique
03484       string aMedName = itGIBItoMED->med_name;
03485       if (!medUniqueNames.insert(aMedName).second) {
03486         string aMedNameNew;
03487         int ind = 1;
03488         char strInd [32];
03489         do {
03490           sprintf(strInd, "_%d", ind++);
03491           aMedNameNew = aMedName + strInd;
03492         } while (!medUniqueNames.insert(aMedNameNew).second);
03493         aMedName = aMedNameNew;
03494       }
03495 
03496       // add to the string
03497       theWholeString += aMedName; // MED name
03498 
03499       // add an offset
03500       currOffset += aMedName.length();
03501       theOffsets.push_back(currOffset);
03502     }
03503     fcount1.stop();
03504   }
03505 
03506   // Table MED_CHAM
03507   if (nbNames_cham) {
03508     // Provide unique MED names, to exclude conflicts on reading saved files
03509     // (use case: read fra.med, save it to GIBI, read it from GIBI,
03510     // save to MED again -> this new MED file is not readable)
03511     set<string> medUniqueNames;
03512 
03513     _gibi << setw(8) << nbNames_cham*4 << endl; // Nb of table values
03514 
03515     TFieldCounter fcount1 (_gibi, 10);
03516     _gibi << right;
03517     list<nameGIBItoMED>::const_iterator itGIBItoMED = listGIBItoMED_cham.begin();
03518     for (; itGIBItoMED != listGIBItoMED_cham.end(); itGIBItoMED++, istr++) {
03519       // PILE of i-th key(med name)
03520       _gibi << setw(8) << 27; fcount1++; // PILE_STRINGS number is 27
03521       // ID of i-th key(med name)
03522       _gibi << setw(8) << istr; fcount1++;
03523 
03524       // PILE of i-th value(gibi name)
03525       // PILE_NODES_FIELD number is 2, PILE_FIELD number is 39
03526       _gibi << setw(8) << itGIBItoMED->gibi_pile; fcount1++;
03527       // ID of i-th value(gibi name)
03528       _gibi << setw(8) << itGIBItoMED->gibi_id; fcount1++;
03529 
03530       // check MED name to be unique
03531       string aMedName = itGIBItoMED->med_name;
03532       if (!medUniqueNames.insert(aMedName).second) {
03533         string aMedNameNew;
03534         int ind = 1;
03535         char strInd [32];
03536         do {
03537           sprintf(strInd, "_%d", ind++);
03538           aMedNameNew = aMedName + strInd;
03539         } while (!medUniqueNames.insert(aMedNameNew).second);
03540         aMedName = aMedNameNew;
03541       }
03542 
03543       // add to the string
03544       theWholeString += aMedName; // MED name
03545 
03546       // add an offset
03547       currOffset += aMedName.length();
03548       theOffsets.push_back(currOffset);
03549     }
03550     fcount1.stop();
03551   }
03552 
03553   // Table MED_COMP
03554   if (nbNames_comp) {
03555     // for components, both key and value (long and short name) is in the STRING PILE
03556 
03557     _gibi << setw(8) << nbNames_comp*4 << endl; // Nb of table values
03558 
03559     TFieldCounter fcount1 (_gibi, 10);
03560     _gibi << right;
03561     list<nameGIBItoMED>::const_iterator itGIBItoMED = listGIBItoMED_comp.begin();
03562     for (; itGIBItoMED != listGIBItoMED_comp.end(); itGIBItoMED++, istr+=2) {
03563       // PILE of i-th key(med name)
03564       _gibi << setw(8) << 27; fcount1++; // PILE_STRINGS number is 27
03565       // ID of i-th key(med name)
03566       _gibi << setw(8) << istr; fcount1++;
03567 
03568       // PILE of i-th value(gibi name)
03569       _gibi << setw(8) << 27; fcount1++; // PILE_STRINGS number is 27
03570       // ID of i-th value(gibi name)
03571       _gibi << setw(8) << istr + 1; fcount1++;
03572 
03573       // add to the string
03574       string aMedName  = itGIBItoMED->med_name;
03575       string aGibiName = itGIBItoMED->gibi_name;
03576       theWholeString += aMedName; // MED name
03577       theWholeString += aGibiName; // GIBI name
03578 
03579       // add offsets
03580       currOffset += aMedName.length();
03581       theOffsets.push_back(currOffset);
03582       currOffset += aGibiName.length();
03583       theOffsets.push_back(currOffset);
03584     }
03585     fcount1.stop();
03586   }
03587 
03588   int nbNames = nbNames_mail + nbNames_cham + 2 * nbNames_comp; // tmp
03589 
03590   // The STRING PILE
03591   // * 800   FORMAT (' ENREGISTREMENT DE TYPE', I4)
03592   _gibi << " ENREGISTREMENT DE TYPE   2" << endl;
03593   // * 801     FORMAT(' PILE NUMERO',I4,'NBRE OBJETS NOMMES',I8,'NBRE OBJETS',I8)
03594   _gibi << " PILE NUMERO  27NBRE OBJETS NOMMES" << setw(8) << 0 << // No named strings
03595     "NBRE OBJETS" << setw(8) << nbNames << endl;
03596 
03597   // Write IDs
03598   //TFieldCounter fcount2 (_gibi, 10);
03599   //_gibi << right;
03600   //for (int jj = 1; jj <= nbNames; jj++) {
03601   //  _gibi << setw(8) << jj; fcount2++;
03602   //}
03603   //fcount2.stop();
03604 
03605   // <LENGTH>     <NB>
03606   _gibi << setw(8) << theWholeString.length()
03607         << setw(8) << nbNames << endl;
03608 
03609   // Write the whole string
03610   const int fixedLength = 71;
03611   int aPos = 0;
03612   int aLen = theWholeString.length();
03613   for (; aPos < aLen; aPos += fixedLength) {
03614     _gibi << setw(72) << theWholeString.substr(aPos, fixedLength) << endl;
03615   } while (aPos < aLen);
03616 
03617   // Write the offsets
03618   TFieldCounter fcount3 (_gibi, 10);
03619   _gibi << right;
03620   list<int>::iterator offsetIt = theOffsets.begin();
03621   for (; offsetIt != theOffsets.end(); offsetIt++) {
03622     _gibi << setw(8) << (*offsetIt); fcount3++;
03623   }
03624   fcount3.stop();
03625 }
03626 
03627 //=======================================================================
03628 //function : writeLastRecord
03629 //purpose  :
03630 //=======================================================================
03631 
03632 void GIBI_MESH_WRONLY_DRIVER::writeLastRecord()
03633 {
03634   _gibi << " ENREGISTREMENT DE TYPE   5" << endl;
03635   _gibi << "LABEL AUTOMATIQUE :   1" << endl;
03636 }
03637 
03638 /*--------------------- RDWR PART -------------------------------*/
03639 
03640 GIBI_MESH_RDWR_DRIVER::GIBI_MESH_RDWR_DRIVER()
03641   :GIBI_MESH_DRIVER(), GIBI_MESH_RDONLY_DRIVER(), GIBI_MESH_WRONLY_DRIVER()
03642 {
03643 }
03644 GIBI_MESH_RDWR_DRIVER::GIBI_MESH_RDWR_DRIVER(const string & fileName, MESH * ptrMesh):
03645   GIBI_MESH_DRIVER(fileName,ptrMesh,RDWR),
03646   GIBI_MESH_RDONLY_DRIVER(fileName,ptrMesh),
03647   GIBI_MESH_WRONLY_DRIVER(fileName,ptrMesh)
03648 {
03649   MESSAGE_MED("GIBI_MESH_RDWR_DRIVER::GIBI_MESH_RDWR_DRIVER(const string & fileName, MESH * ptrMesh) has been created");
03650 }
03651 GIBI_MESH_RDWR_DRIVER::GIBI_MESH_RDWR_DRIVER(const GIBI_MESH_RDWR_DRIVER & driver):
03652   GIBI_MESH_DRIVER(driver),
03653   GIBI_MESH_RDONLY_DRIVER(driver),
03654   GIBI_MESH_WRONLY_DRIVER(driver)
03655 {
03656   MESSAGE_MED("GIBI_MESH_RDWR_DRIVER::GIBI_MESH_RDWR_DRIVER(driver) has been created");
03657 }
03658 GIBI_MESH_RDWR_DRIVER::~GIBI_MESH_RDWR_DRIVER() {
03659   MESSAGE_MED("GIBI_MESH_RDWR_DRIVER::GIBI_MESH_RDWR_DRIVER(const string & fileName, MESH * ptrMesh) has been destroyed");
03660 }
03661 GENDRIVER * GIBI_MESH_RDWR_DRIVER::copy(void) const
03662 {
03663   const char* LOC = "GIBI_MESH_RDWR_DRIVER::copy()";
03664   BEGIN_OF_MED(LOC);
03665   GENDRIVER * driver = new GIBI_MESH_RDWR_DRIVER(*this);
03666   END_OF_MED(LOC);
03667   return driver;
03668 }
03669 void GIBI_MESH_RDWR_DRIVER::write(void) const
03670   throw (MEDEXCEPTION)
03671 {
03672   GIBI_MESH_RDWR_DRIVER * me = const_cast<GIBI_MESH_RDWR_DRIVER *>(this);
03673   me->GIBI_MESH_WRONLY_DRIVER::open();
03674   me->GIBI_MESH_WRONLY_DRIVER::write();
03675   me->GIBI_MESH_WRONLY_DRIVER::close();
03676 }
03677 void GIBI_MESH_RDWR_DRIVER::read (void)
03678   throw (MEDEXCEPTION)
03679 {
03680   const char* LOC = "GIBI_MESH_RDWR_DRIVER::read()";
03681   BEGIN_OF_MED(LOC);
03682   GIBI_MESH_RDONLY_DRIVER::open();
03683   GIBI_MESH_RDONLY_DRIVER::read();
03684   GIBI_MESH_RDONLY_DRIVER::close();
03685   END_OF_MED(LOC);
03686 }
03687 void GIBI_MESH_RDWR_DRIVER::open()
03688   // throw (MEDEXCEPTION)
03689 {
03690 }
03691 void GIBI_MESH_RDWR_DRIVER::close()
03692   // throw (MEDEXCEPTION)
03693 {
03694 }
03695 
03696 //============================== ====================================================
03697 //============================== FIELD Reading Driver ==============================
03698 //============================== ====================================================
03699 
03700 GIBI_MED_RDONLY_DRIVER::GIBI_MED_RDONLY_DRIVER():GIBI_MESH_RDONLY_DRIVER(),_fields(0)
03701 {
03702 }
03703 GIBI_MED_RDONLY_DRIVER::GIBI_MED_RDONLY_DRIVER(const string & fileName, vector<FIELD_*>& ptrFields):
03704   GIBI_MESH_RDONLY_DRIVER(fileName,NULL), _fields( &ptrFields )
03705 {
03706   MESSAGE_MED("GIBI_MED_RDONLY_DRIVER(const string & fileName, vector<FIELD_*>&) has been created");
03707   _fileName = fileName;
03708   _accessMode = RDONLY;
03709 }
03710 GIBI_MED_RDONLY_DRIVER::GIBI_MED_RDONLY_DRIVER(const GIBI_MED_RDONLY_DRIVER & driver):
03711   GIBI_MESH_RDONLY_DRIVER( driver ), _fields( driver._fields )
03712 {
03713 }
03714 
03715 GIBI_MED_RDONLY_DRIVER::~GIBI_MED_RDONLY_DRIVER()
03716 {
03717   if ( _mesh )
03718     _mesh->removeReference();
03719 }
03720 GENDRIVER * GIBI_MED_RDONLY_DRIVER::copy ( void ) const
03721 {
03722   return new GIBI_MED_RDONLY_DRIVER(*this);
03723 }
03724 
03725 //=======================================================================
03726 //function : read
03727 //purpose  :
03728 //=======================================================================
03729 
03730 void GIBI_MED_RDONLY_DRIVER::read ( void ) throw (MEDEXCEPTION)
03731 {
03732   const char * LOC = "GIBI_MED_RDONLY_DRIVER::read() : ";
03733   BEGIN_OF_MED(LOC);
03734 
03735   if (_status!=MED_OPENED)
03736     throw MEDEXCEPTION(LOCALIZED(STRING(LOC) << "file " << _fileName<<" is not opened." ));
03737 
03738   _mesh = new MESH;
03739 
03740   _intermediateMED medi;
03741   try {
03742     if ( !readFile( &medi, true ) )
03743       return;
03744 
03745     //MESSAGE_MED(LOC <<  medi );
03746     fillMesh( &medi );
03747     MESSAGE_MED(LOC << "GIBI_MED_RDONLY_DRIVER::read : RESULTATS STRUCTURE INTERMEDIAIRES : ");
03748     MESSAGE_MED(LOC <<  medi );
03749 
03750     list< FIELD_* > fields;
03751     medi.getFields( fields );
03752     updateSupports(); // create families from groups etc.
03753     MESSAGE_MED( "nb fields: " << fields.size() );
03754 
03755     if ( _mesh->getName().empty() )
03756       _mesh->setName( "MESH" );
03757 
03758     list< FIELD_* >::iterator it = fields.begin();
03759     for ( ; it != fields.end(); it++ )
03760     {
03761       FIELD_* fld = *it;
03762       int nbComponents = fld->getNumberOfComponents();
03763       if(nbComponents>0) {
03764         UNIT* compoUnits = new UNIT[nbComponents];
03765         string* MEDcompoUnits = new string[nbComponents];
03766         for(int l = 0; l<nbComponents; l++) {
03767           compoUnits[l] = UNIT("", "");
03768           MEDcompoUnits[l] = "";
03769         }
03770         fld->setComponentsUnits(compoUnits);
03771         fld->setMEDComponentsUnits(MEDcompoUnits);
03772         delete [] compoUnits;
03773         delete [] MEDcompoUnits;
03774       }
03775       // 0020466: [CEA] sauv2med : bad conversion
03776       // Provide profile names for a partial field
03777       const SUPPORT* sup = fld->getSupport();
03778       if ( sup && !sup->isOnAllElements() )
03779       {
03780         vector<string> prof_names( sup->getNumberOfTypes() );
03781         for (unsigned itype=0; itype < prof_names.size(); itype++)
03782           prof_names[itype]=STRING( sup->getName())<<"_type"<<sup->getTypes()[itype];
03783         ((SUPPORT*) sup)->setProfilNames( prof_names );
03784       }
03785       _fields->push_back( *it );
03786     }
03787   }
03788   catch (MEDEXCEPTION &ex)
03789   {
03790     INFOS_MED( ex.what() );
03791   }
03792 
03793   END_OF_MED(LOC);
03794 }
03795 
03796 //================================================================================
03801 //================================================================================
03802 
03803 MESH* GIBI_MED_RDONLY_DRIVER::getMesh() const
03804 {
03805   if ( _mesh )
03806     _mesh->addReference();
03807   return (MESH*) _mesh;
03808 }
03809 
03810 
03811 //============================== ====================================================
03812 //============================== FIELD Writting Driver ==============================
03813 //============================== ====================================================
03814 
03815 GIBI_MED_WRONLY_DRIVER::GIBI_MED_WRONLY_DRIVER():GIBI_MESH_WRONLY_DRIVER()
03816 {
03817 }
03818 GIBI_MED_WRONLY_DRIVER::GIBI_MED_WRONLY_DRIVER(const string &               fileName,
03819                                                const vector<const FIELD_*>& fields,
03820                                                GMESH *                      ptrMesh)
03821   :GIBI_MESH_DRIVER(fileName,ptrMesh,WRONLY),
03822    GIBI_MESH_WRONLY_DRIVER(fileName,ptrMesh),
03823    _fields( fields )
03824 {
03825   const char * LOC = "GIBI_MED_WRONLY_DRIVER( fileName, vector<FIELD_*>&, MESH *)";
03826   BEGIN_OF_MED(LOC);
03827 
03828   if ( !_mesh )
03829     throw MEDEXCEPTION(LOCALIZED(STRING(LOC) << " Bad mesh " << _mesh ));
03830   _fileName = fileName;
03831   _accessMode = WRONLY;
03832 }
03833 
03834 GIBI_MED_WRONLY_DRIVER::GIBI_MED_WRONLY_DRIVER(const GIBI_MED_WRONLY_DRIVER & driver):
03835   GIBI_MESH_WRONLY_DRIVER( driver ), _fields( driver._fields )
03836 {
03837 }
03838 GIBI_MED_WRONLY_DRIVER::~GIBI_MED_WRONLY_DRIVER()
03839 {
03840 }
03841 GENDRIVER * GIBI_MED_WRONLY_DRIVER::copy ( void ) const
03842 {
03843   return new GIBI_MED_WRONLY_DRIVER(*this);
03844 }
03845 
03846 //=======================================================================
03847 //function : writeDataSection
03848 //purpose  :
03849 //=======================================================================
03850 
03851 template< class T, class INTERLACING_TAG>
03852 static void writeDataSection (fstream&                          file,
03853                               const FIELD<T, INTERLACING_TAG> * field,
03854                               const int                         id1,
03855                               const int                         id2) throw (MEDEXCEPTION)
03856 {
03857   const char * LOC="writeDataSection (.....) :";
03858   BEGIN_OF_MED(LOC);
03859 
03860   int nbGauss, nbComp = field->getNumberOfComponents();
03861 
03862   typedef typename MEDMEM_ArrayInterface<T,INTERLACING_TAG,NoGauss>::Array ArrayNoGauss;
03863   typedef typename MEDMEM_ArrayInterface<T,INTERLACING_TAG,Gauss>::Array   ArrayGauss;
03864 
03865   MEDMEM_Array_ * array        = field->getArray();
03866   ArrayNoGauss  * arrayNoGauss = 0;
03867   ArrayGauss    * arrayGauss   = 0;
03868 
03869   if ( !array )
03870     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<" Field |"<< field->getName()
03871                                  << "| not allocated"));
03872 
03873   if ( array->getGaussPresence() ) {
03874     arrayGauss = field->getArrayGauss();
03875     nbGauss    = arrayGauss->getNbGauss( id1 );
03876   }
03877   else {
03878     arrayNoGauss = field->getArrayNoGauss();
03879     nbGauss      = 1;
03880   }
03881 
03882   TFieldCounter fcount( file, 3 ); // 3 values on a line
03883 
03884 #ifdef CASTEM_FULL_INTERLACE
03885   const int gauss_step = field->getInterlacingType() == MED_EN::MED_FULL_INTERLACE ? nbComp : 1;
03886 #endif
03887   const bool isNodal = ( field->getSupport()->getEntity() == MED_EN::MED_NODE );
03888 
03889   for ( int iComp = 1; iComp <= nbComp; ++iComp )
03890   {
03891     if ( !isNodal )
03892       file << setw(8) << nbGauss       // nb scalar values by element
03893            << setw(8) << ( id2 - id1 ) // total nb of scalar values
03894            << setw(8) << 0
03895            << setw(8) << 0
03896            << endl;
03897 
03898     // * 8003   FORMAT(1P,3E22.14)
03899     if ( arrayNoGauss ) {
03900       for (int id = id1; id < id2; id++, fcount++ )
03901         file << setw(22) << arrayNoGauss->getIJ( id, iComp );
03902     }
03903     else {
03904 #ifdef CASTEM_FULL_INTERLACE
03905       for (int id = id1; id < id2; id++ ) {
03906         const T* val = & arrayGauss->getIJK( id, iComp, 1 );
03907         const T* valEnd = val + nbGauss * gauss_step;
03908         for ( ; val < valEnd; val += gauss_step, fcount++ )
03909           file << setw(22) << *val;
03910       }
03911 #else
03912       for ( int iGauss = 1; iGauss <= nbGauss; ++iGauss ) {
03913         for (int id = id1; id < id2; id++, fcount++  )
03914           file << setw(22) << arrayGauss->getIJK( id, iComp, iGauss );
03915       }
03916 #endif
03917     }
03918     fcount.stop();
03919   }
03920   END_OF_MED(LOC);
03921 }
03922 
03923 //=======================================================================
03924 //function : write
03925 //purpose  :
03926 //=======================================================================
03927 
03928 void GIBI_MED_WRONLY_DRIVER::write( void ) const throw (MEDEXCEPTION)
03929 {
03930   const char* LOC = "void GIBI_MED_WRONLY_DRIVER::write(void) const : ";
03931   BEGIN_OF_MED(LOC);
03932 
03933   // we are going to modify the _gibi field
03934   GIBI_MED_WRONLY_DRIVER * me = const_cast<GIBI_MED_WRONLY_DRIVER *>(this);
03935 
03936   // get all fields on _mesh and add their support to be written
03937   list<const FIELD_*> fields;
03938   int iField, nbFields = _fields.size();
03939   list<int> nb_sub_list, nb_comp_list;
03940   int nb_nodal_flds = 0;
03941 
03942   map<string,int> nameNbMap;
03943   map<string,int> namePrefixMap;
03944   list< string > orderedNames;
03945 
03946   list<pair<int,int> >           subIdSizeList; // pair( <submesh id>, <submesh size> );
03947   list<pair<int,int> >::iterator idsize;
03948 
03949   // IMP 0020434: mapping GIBI names to MED names
03950   list<nameGIBItoMED> listGIBItoMED_mail;
03951   list<nameGIBItoMED> listGIBItoMED_cham;
03952   list<nameGIBItoMED> listGIBItoMED_comp;
03953 
03954   for ( iField = 0; iField < nbFields; ++iField )
03955     {
03956       int nb_sub = 0, nb_comp = 0;
03957       const FIELD_ * f = _fields[ iField ];
03958       if ( f->getValueType() != MED_EN::MED_REEL64 )
03959         {
03960           MESSAGE_MED("GIBI_MED_WRONLY_DRIVER::write( FIELD< int > ) not implemented");
03961           continue;
03962         }
03963       const SUPPORT * sup = f->getSupport();
03964       const medEntityMesh entity = sup->getEntity();
03965 
03966       if ( me->addSupport( sup ) )
03967         {
03968           if ( entity == MED_NODE ) fields.push_front( f );
03969           else                      fields.push_back( f );
03970           nb_sub += getSubMeshIdAndSize( sup, subIdSizeList );
03971           nb_comp += nb_sub * f->getNumberOfComponents();
03972         }
03973       if ( nb_sub )
03974         {
03975           if ( entity == MED_NODE )
03976             {
03977               nb_sub_list.push_front ( nb_sub );
03978               orderedNames.push_front( f->getName() );
03979               nb_comp_list.push_front( nb_comp );
03980               nb_nodal_flds++;
03981             }
03982           else
03983             {
03984               nb_sub_list.push_back ( nb_sub );
03985               orderedNames.push_back( f->getName() );
03986               nb_comp_list.push_back( nb_comp );
03987             }
03988         }
03989     }
03990   list< string >::iterator nameIt = orderedNames.begin();
03991   for ( iField = 0 ; nameIt != orderedNames.end(); ++nameIt, ++iField )
03992     {
03993       const bool isNodal = iField < nb_nodal_flds;
03994       int nb_obj = isNodal ? (iField + 1) : (iField - nb_nodal_flds + 1);
03995       addName(nameNbMap, namePrefixMap, *nameIt, nb_obj);
03996 
03997       // IMP 0020434: mapping GIBI names to MED names
03998       nameGIBItoMED aMEDName;
03999       aMEDName.gibi_pile = isNodal ? PILE_NODES_FIELD : PILE_FIELD;
04000       aMEDName.gibi_id   = nb_obj;
04001       aMEDName.med_name  = *nameIt;
04002       listGIBItoMED_cham.push_back(aMEDName);
04003     }
04004 
04005   // write the mesh
04006 
04007   me->writeSupportsAndMesh(listGIBItoMED_mail);
04008 
04009   // write fields
04010 
04011   if ( !fields.empty() )
04012     {
04013       fstream & gibi = me->_gibi;
04014 
04015       TFieldCounter fcount( gibi, 10 );
04016 
04017       list<const FIELD_*>::const_iterator itF = fields.begin();
04018       list<int>::iterator itNbSub = nb_sub_list.begin(), itNbComp = nb_comp_list.begin();
04019       int nb_sub = 0, cur_nb_sub = 0, total_nb_comp = 0;
04020       medEntityMesh entity = MED_INVALID;
04021 
04022       for ( iField = 0; itF != fields.end(); itF++, iField++ )
04023         {
04024           const FIELD_* f = *itF;
04025 
04026           unsigned iComp, nbComp = unsigned( f->getNumberOfComponents() );
04027 
04028           // IMP 0020434: mapping GIBI names to MED names
04029           map<string, string> mapMedToGibi;
04030           {
04031             for (int ico = 0; ico < nbComp; ico++)
04032               {
04033                 string compMedName = f->getComponentName(ico + 1);
04034                 compMedName = cleanName(compMedName);
04035                 mapMedToGibi[compMedName] = compMedName;
04036               }
04037             int compIndex = 1;
04038             map<string, string>::iterator namesIt = mapMedToGibi.begin();
04039             for (; namesIt != mapMedToGibi.end(); namesIt++)
04040               {
04041                 string compMedName = (*namesIt).first;
04042                 string compGibiName = compMedName;
04043                 if (compGibiName.size() > 4) {
04044                   // use new name in form "CXXX", where "XXX" is a number
04045                   do
04046                     {
04047                       char strCGN [32];
04048                       strCGN[0] = 'C';
04049                       int pos = 1;
04050                       if (compIndex < 100) strCGN[pos++] = '0';
04051                       if (compIndex < 10 ) strCGN[pos++] = '0';
04052                       sprintf(strCGN + pos, "%d", compIndex++);
04053                       compGibiName = strCGN;
04054                     }
04055                   while (mapMedToGibi.count(compGibiName) > 0); // real component name could be CXXX
04056 
04057                   mapMedToGibi[compMedName] = compGibiName;
04058                 }
04059 
04060                 compMedName = f->getName() + "." + compMedName;
04061                 nameGIBItoMED aMEDName;
04062                 aMEDName.med_name  = compMedName;
04063                 aMEDName.gibi_pile = PILE_STRINGS;
04064                 aMEDName.gibi_name = compGibiName;
04065                 listGIBItoMED_comp.push_back(aMEDName);
04066               }
04067           } // IMP 0020434
04068 
04069           if ( cur_nb_sub == nb_sub && itNbSub != nb_sub_list.end() )
04070             {
04071               // Start writting another field
04072 
04073               const medEntityMesh nextEntity = f->getSupport()->getEntity();
04074               if ( nextEntity != entity )
04075                 {
04076                   if ( entity == MED_INVALID || entity == MED_NODE )
04077                     {
04078                       int nb_obj = ( nextEntity == MED_NODE ) ? nb_nodal_flds : orderedNames.size() - nb_nodal_flds;
04079                       gibi << " ENREGISTREMENT DE TYPE   2" << endl;
04080                       gibi << " PILE NUMERO" << ( nextEntity == MED_NODE ? "   2" : "  39" );
04081                       gibi << "NBRE OBJETS NOMMES" << setw(8) << nameNbMap.size();
04082                       gibi << "NBRE OBJETS" << setw(8) << nb_obj << endl;
04083 
04084                       me->writeNames( nameNbMap );
04085                     }
04086                   entity = f->getSupport()->getEntity();
04087                 }
04088 
04089               total_nb_comp = *(itNbComp++);
04090               nb_sub        = *(itNbSub++);
04091 
04092               string description = (*itF)->getDescription();
04093               if ( description.size() > 72 )
04094                 description = description.substr(0,72);
04095 
04096               if ( entity == MED_NODE )
04097                 {
04098                   gibi << setw(8) << nb_sub
04099                        << setw(8) << total_nb_comp
04100                        << setw(8) << -1         // IFOUR
04101                        << setw(8) << 0 << endl; // nb attributes
04102                 }
04103               else
04104                 {
04105                   gibi << setw(8) << nb_sub
04106                        << setw(8) << -1
04107                        << setw(8) << 6
04108                        << setw(8) << 72 /*description.size()*/ << endl; // PAL19100
04109                   if ( !description.empty() )
04110                     gibi << setw(72) << description << endl;
04111                   else
04112                     gibi << setw(72) << "Field" << endl;
04113                   gibi << setw(72) << " " << endl;
04114                 }
04115 
04116               // Sub Components section
04117 
04118               list<const FIELD_*>::const_iterator itF2 = itF;
04119               int vals[9] =
04120                 {
04121                   0, 0, 0, 0, 0, 0, 0, 0, 2
04122                 };
04123               const int nbv = ( entity == MED_NODE ? 3 : 9 );
04124               vector< string > comp_names;
04125               fcount.init(10);
04126               cur_nb_sub = 0;
04127               while ( itF2 != fields.end() && cur_nb_sub < nb_sub )
04128                 {
04129                   const FIELD_* f = *itF2++;
04130                   vals[2] = f->getNumberOfComponents();
04131                   getSubMeshIdAndSize( f->getSupport(), subIdSizeList );
04132                   for ( idsize = subIdSizeList.begin(); idsize != subIdSizeList.end(); idsize++)
04133                     {
04134                       ++cur_nb_sub;
04135 
04136                       vals[0] = -idsize->first; // support id
04137                       if ( entity == MED_NODE )
04138                         vals[1] = idsize->second; // nb values
04139                       for ( int i = 0; i < nbv; ++i, fcount++ )
04140                         gibi << setw(8) << vals[ i ];
04141 
04142                       for ( int i = 0; i < f->getNumberOfComponents(); ++i )
04143                         comp_names.push_back( f->getComponentName( i+1 ));
04144                     }
04145                 }
04146               fcount.stop();
04147               cur_nb_sub = 0;
04148 
04149               if ( entity == MED_NODE )
04150                 {
04151                   // component names
04152                   fcount.init(8);
04153                   gibi << left;
04154                   {
04155                     for ( iComp = 0; iComp < comp_names.size(); ++iComp, fcount++ )
04156                       {
04157                         string compMedName = cleanName(f->getComponentName(iComp + 1));
04158                         string compName = mapMedToGibi[compMedName];
04159                         gibi << " "  << setw(8) << compName;
04160                       }
04161                   }
04162                   gibi << right;
04163                   fcount.stop();
04164 
04165                   // nb harmonics
04166                   fcount.init(10);
04167                   for ( int i = 0; i < total_nb_comp; ++i )
04168                     gibi << setw(8) << 0;
04169                   fcount.stop();
04170 
04171                   gibi << endl; // TYPE
04172                   gibi << setw(72) << description << endl;
04173                   gibi << endl; // 0 attributes
04174                 }
04175               else
04176                 {
04177                   // dummy strings
04178                   int i_sub;
04179                   for ( fcount.init(4), i_sub = 0; i_sub < nb_sub; ++i_sub, fcount++ )
04180                     gibi << "                  ";
04181                   fcount.stop();
04182 
04183                   for ( fcount.init(8), i_sub = 0; i_sub < nb_sub; ++i_sub, fcount++ )
04184                     gibi << "         ";
04185                   fcount.stop();
04186                 }
04187             } // end writing common field data
04188 
04189 
04190           // loop on sub-components
04191           int id1 = 1;
04192           getSubMeshIdAndSize( f->getSupport(), subIdSizeList );
04193           for ( idsize = subIdSizeList.begin(); idsize != subIdSizeList.end(); idsize++ )
04194             {
04195               cur_nb_sub++;
04196               if ( entity != MED_NODE )
04197                 {
04198                   // component addresses
04199                   fcount.init(10);
04200                   for ( iComp = 0; iComp < nbComp; ++iComp, fcount++ )
04201                     gibi << setw(8) << 777; // a good number
04202                   fcount.stop();
04203                   // component names
04204                   gibi << left;
04205                   fcount.init(8);
04206                   for ( iComp = 0; iComp < nbComp; ++iComp, fcount++ )
04207                     {
04208                       string compMedName = cleanName(f->getComponentName(iComp + 1));
04209                       string compName    = mapMedToGibi[compMedName];
04210                       gibi << " "  << setw(8) << compName;
04211                     }
04212                   fcount.stop();
04213                   // component types
04214                   fcount.init(4);
04215                   for ( iComp = 0; iComp < nbComp; ++iComp, fcount++ )
04216                     gibi << " "  << setw(17) << "REAL*8";
04217                   fcount.stop();
04218                   gibi << right;
04219                 }
04220 
04221               // Data section
04222 
04223               int id2 = id1 + idsize->second;
04224 
04225               if ( f->getInterlacingType() == MED_NO_INTERLACE )
04226                 writeDataSection( gibi, static_cast<const FIELD<double,NoInterlace  > * >(f),
04227                                   id1, id2 );
04228               else if ( f->getInterlacingType() == MED_FULL_INTERLACE )
04229                 writeDataSection( gibi, static_cast<const FIELD<double,FullInterlace> * >(f),
04230                                   id1, id2 );
04231               else
04232                 writeDataSection( gibi, static_cast<const FIELD<double,NoInterlaceByType> * >(f),
04233                                   id1, id2 );
04234 
04235               id1 = id2;
04236             }
04237         } // loop on fields
04238     }
04239 
04240   // IMP 0020434: mapping GIBI names to MED names
04241   me->writeMEDNames(listGIBItoMED_mail, listGIBItoMED_cham, listGIBItoMED_comp);
04242 
04243   me->writeLastRecord();
04244 
04245   END_OF_MED(LOC);
04246 }