]> SALOME platform Git repositories - modules/med.git/blob - src/MEDMEM/MEDMEM_PorflowMeshDriver.cxx
Salome HOME
update due to bugs PAL8113 and another I do not remember the number ;) .
[modules/med.git] / src / MEDMEM / MEDMEM_PorflowMeshDriver.cxx
1 #include "MEDMEM_PorflowMeshDriver.hxx"
2 #include "MEDMEM_DriversDef.hxx"
3 #include "MEDMEM_DriverTools.hxx"
4
5 #include "MEDMEM_Family.hxx"
6 #include "MEDMEM_Group.hxx"
7 #include "MEDMEM_Coordinate.hxx"
8 #include "MEDMEM_Connectivity.hxx"
9 #include "MEDMEM_Mesh.hxx"
10 #include "MEDMEM_CellModel.hxx"
11 #include "MEDMEM_define.hxx"
12 #include <string.h>
13 #include <ctype.h>
14 #include <iostream>
15 #include <sstream>
16 #include <iomanip>
17
18 using namespace std;
19 using namespace MED_EN;
20 using namespace MEDMEM;
21
22 // geometric types conversion from PORFLOW -> MED
23 const size_t PORFLOW_MESH_DRIVER::nb_geometrie_porflow;
24 const medGeometryElement PORFLOW_MESH_DRIVER::geomPORFLOWtoMED[nb_geometrie_porflow] =
25   {   /*  1  */ MED_TRIA3   ,/*  2  */ MED_QUAD4  ,/*  3  */ MED_TETRA4  ,/*  4  */ MED_PYRA5  ,
26       /*  5  */ MED_PENTA6  ,/*  6  */ MED_HEXA8   };
27 // indirection table from PORFLOW order to MED one for nodes numerotation in all PORFLOW geometries
28 const size_t PORFLOW_MESH_DRIVER::nb_nodes_max;
29
30 // conversion from porflow connectivity to MED connectivity
31 const int PORFLOW_MESH_DRIVER::numPORFLOWtoMED[nb_geometrie_porflow] [nb_nodes_max] = {
32       /*  TRI3   */ { /*1*/ 1, /*2*/ 3, /*3*/ 2 },
33       /*  QUA4   */ { /*1*/ 1, /*2*/ 4, /*3*/ 3, /*4*/ 2 },
34       /*  TETRA4 */ { /*1*/ 1, /*2*/ 4, /*3*/ 3, /*4*/ 2 },
35       /*  PYRA5  */ { /*1*/ 1, /*2*/ 4, /*3*/ 3, /*4*/ 2, /*5*/ 5 },
36       /*  PENTA6 */ { /*1*/ 1, /*2*/ 3, /*3*/ 2, /*4*/ 4, /*5*/ 6, /*6*/ 5 },
37       /*  HEXA8  */ { /*1*/ 1, /*2*/ 4, /*3*/ 3, /*4*/ 2, /*5*/ 5, /*6*/ 8, /*7*/ 7, /*8*/ 6 } };
38
39 // Porflox nodal connectivity of faces - documented in Porflow user's manual
40 const size_t PORFLOW_MESH_DRIVER::nb_faces_max;
41 const size_t PORFLOW_MESH_DRIVER::nb_nodes2_max;
42 const int PORFLOW_MESH_DRIVER::connectivityPORFLOW[nb_geometrie_porflow][nb_faces_max][nb_nodes2_max]={
43   //{/* TRI3   */ {3,1,0,0}, {1,2,0,0}, {2,3,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0} },
44   //{/* QUA4   */ {1,4,0,0}, {2,3,0,0}, {1,2,0,0}, {3,4,0,0}, {0,0,0,0}, {0,0,0,0} },
45     {/* TRI3   */ {1,3,0,0}, {2,1,0,0}, {3,2,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0} },
46     {/* QUA4   */ {1,4,0,0}, {3,2,0,0}, {2,1,0,0}, {4,3,0,0}, {0,0,0,0}, {0,0,0,0} },
47     {/* TETRA4 */ {1,3,4,0}, {1,4,2,0}, {4,3,2,0}, {1,2,3,0}, {0,0,0,0}, {0,0,0,0} },
48     {/* PYRA5  */ {1,4,5,0}, {1,5,2,0}, {3,2,5,0}, {4,3,5,0}, {1,2,3,4}, {0,0,0,0} },
49     {/* PENTA6 */ {1,3,6,4}, {2,1,4,5}, {3,2,5,6}, {1,2,3,0}, {4,6,5,0}, {0,0,0,0} },
50     {/* HEXA8  */ {1,4,8,5}, {3,2,6,7}, {2,1,5,6}, {4,3,7,8}, {1,2,3,4}, {5,8,7,6} },
51 };
52
53 // helper function
54 inline static bool isKeyWord(const string & line, const char * key);
55 inline static void locateFileName(const string& line, string::size_type& pos1, string::size_type& pos2);
56 inline static string getPorflowFileName(const string& line, const char * context);
57 inline static medGeometryElement get2DMedGeomType(int nbSommets);
58
59
60 // Every memory allocation made in the MedDriver members function are desallocated in the Mesh destructor 
61
62 PORFLOW_MESH_DRIVER::PORFLOW_MESH_DRIVER():
63   GENDRIVER(),
64   _ptrMesh(( MESH *)MED_NULL),
65   // A VOIR _medIdt(MED_INVALID),
66   _meshName("")
67 {
68 }
69
70 PORFLOW_MESH_DRIVER::PORFLOW_MESH_DRIVER(const string & fileName,
71                                    MESH * ptrMesh,
72                                    MED_EN::med_mode_acces accessMode): 
73   GENDRIVER(fileName,accessMode),
74   _ptrMesh(ptrMesh)
75 {
76     // mesh name construction from fileName
77     const string ext=".inp"; // expected extension
78     string::size_type pos=fileName.find(ext,0);
79     string::size_type pos1=fileName.rfind('/');
80     _meshName = string(fileName,pos1+1,pos-pos1-1); //get rid of directory & extension
81     SCRUTE(_meshName);
82 }
83   
84 PORFLOW_MESH_DRIVER::PORFLOW_MESH_DRIVER(const PORFLOW_MESH_DRIVER & driver): 
85   GENDRIVER(driver),
86   _ptrMesh(driver._ptrMesh),
87   // A VOIR _medIdt(MED_INVALID), 
88   _meshName(driver._meshName)
89 {
90 }
91
92 PORFLOW_MESH_DRIVER::~PORFLOW_MESH_DRIVER()
93 {
94 }
95
96 void PORFLOW_MESH_DRIVER::open()
97   throw (MEDEXCEPTION)
98 {
99     const char * LOC = "PORFLOW_MESH_DRIVER::open()" ;
100     BEGIN_OF(LOC);
101     _porflow.open(_fileName.c_str(), ios::in);
102     if(_porflow)
103         _status = MED_OPENED;
104     else
105     {
106         _status = MED_CLOSED;
107         throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<" Could not open file "<<_fileName<<" in mode ios::in"));
108     }
109     END_OF(LOC);
110 }
111   
112 void PORFLOW_MESH_DRIVER::close()
113   throw (MEDEXCEPTION)
114 {
115     const char * LOC = "PORFLOW_MESH_DRIVER::close() " ;
116     BEGIN_OF(LOC);
117     if ( _status == MED_OPENED) 
118     {
119         _porflow.close();
120         _status = MED_CLOSED;
121     }
122     END_OF(LOC);
123 }
124
125 void    PORFLOW_MESH_DRIVER::setMeshName(const string & meshName) { _meshName = meshName; };
126 string  PORFLOW_MESH_DRIVER::getMeshName() const { return _meshName; };
127
128
129 //---------------------------------- RDONLY PART -------------------------------------------------------------
130
131 PORFLOW_MESH_RDONLY_DRIVER::PORFLOW_MESH_RDONLY_DRIVER(): PORFLOW_MESH_DRIVER()
132 {
133 }
134   
135 PORFLOW_MESH_RDONLY_DRIVER::PORFLOW_MESH_RDONLY_DRIVER(const string & fileName,
136                                                  MESH * ptrMesh):
137   PORFLOW_MESH_DRIVER(fileName,ptrMesh,MED_RDONLY)
138
139   MESSAGE("PORFLOW_MESH_RDONLY_DRIVER::PORFLOW_MESH_RDONLY_DRIVER(const string & fileName, MESH * ptrMesh) has been created");
140 }
141   
142 PORFLOW_MESH_RDONLY_DRIVER::PORFLOW_MESH_RDONLY_DRIVER(const PORFLOW_MESH_RDONLY_DRIVER & driver): 
143   PORFLOW_MESH_DRIVER(driver)
144 {
145 }
146
147 PORFLOW_MESH_RDONLY_DRIVER::~PORFLOW_MESH_RDONLY_DRIVER()
148 {
149   //MESSAGE("PORFLOW_MESH_RDONLY_DRIVER::~PORFLOW_MESH_RDONLY_DRIVER() has been destroyed");
150 }
151   
152 GENDRIVER * PORFLOW_MESH_RDONLY_DRIVER::copy(void) const
153 {
154   return new PORFLOW_MESH_RDONLY_DRIVER(*this);
155 }
156
157 // helper function to check if line starts with key
158 inline static bool isKeyWord(const string & line, const char * key)
159 {
160     const int SIZE_KEY=4;
161     const char * pt=line.c_str();
162     while( isspace(*pt) ) // get rid of leading blanks
163         ++pt;
164     return !strncmp(pt,key,SIZE_KEY);
165 }
166
167 inline static void locateFileName(const string& line, string::size_type& pos1, string::size_type& pos2)
168 {
169     pos1 = line.find('"',0);
170     if ( pos1 != string::npos ) // if we found "
171         pos2=line.find('"',pos1+1); // search a second "
172     else // we didn't succeed with double quotes, so we try single quotes
173     {
174         pos1 = line.find('\'',0);
175         if ( pos1 != string::npos ) // if we found '
176             pos2=line.find('\'',pos1+1); // search a second '
177     }
178 }
179
180
181 // helper fonction : inversion of PORFLOW_MESH_DRIVER::geomPORFLOWtoMED
182 // return the Porflow geometric type, -1 if not found
183 inline int PORFLOW_MESH_DRIVER::geomMEDtoPorflow(medGeometryElement medGeo)
184 {
185     for (int g=0; g!=nb_geometrie_porflow; ++g)
186         if( medGeo == geomPORFLOWtoMED[g] )
187             return g;
188     return -1;
189 }
190
191
192 // Correspondance between the number of nodes and the Med face geometric type
193 inline static medGeometryElement get2DMedGeomType(int nbSommets)
194 {
195     switch (nbSommets)
196     {
197         case 2:
198             return MED_SEG2;
199             break;
200         case 3:
201             return MED_TRIA3;
202             break;
203         case 4:
204             return MED_QUAD4;
205             break;
206     } 
207 }
208
209 // helper function to read a porflow file name (enclosed in single or double quotes) in line
210 inline static string getPorflowFileName(const string& line, const char * context)
211 {
212     string::size_type pos1=string::npos;
213     string::size_type pos2=string::npos;
214
215     locateFileName(line, pos1, pos2);
216
217     // if we found a not empty filename
218     if (pos1 != string::npos && pos2 != string::npos && pos2>pos1+1)
219         return string(line,pos1+1,pos2-pos1-1);
220
221     // else, we throw an exception
222     string diagnosis("PORFLOW_MESH_RDONLY_DRIVER::read() : Error after reading keyword ");
223     diagnosis+=context;
224     diagnosis+="\nNo filename was found enclosed in single or double quotes\n";
225     throw MEDEXCEPTION(diagnosis.c_str());
226 }
227
228
229 // helper function to read a porflow coordinate file ( .xyz )
230 void PORFLOW_MESH_RDONLY_DRIVER::readPorflowCoordinateFile(const string & coorFileName,_intermediateMED & medi,const int space_dimension)
231 {
232
233     ifstream coorFile(coorFileName.c_str(), ios::in);
234     if(!coorFile)
235     {
236         string diagnosis("PORFLOW_MESH_RDONLY_DRIVER::read()\nError, can't open coordinates file :");
237         diagnosis+=coorFileName;
238         throw MEDEXCEPTION(diagnosis.c_str());
239     }
240     
241     // scan of the coord file
242     _noeud node;
243     node.coord.resize(space_dimension);
244     string buf_ligne; // to read a line
245     while ( getline(coorFile, buf_ligne) ) // we can't use input stream directly because some 2D files have "0.0" in third coordinate
246       {
247         istringstream buf(buf_ligne.c_str());
248         buf >> node.number;
249         if (!buf) // for spaces at the end of the file
250           break;
251         for (unsigned i=0; i!=space_dimension; ++i)
252           buf >> node.coord[i];
253         medi.points.insert(make_pair(node.number,node));
254       }
255     coorFile.close();
256 }
257
258 // helper function to read a porflow connectivity file ( .cnc )
259 void PORFLOW_MESH_RDONLY_DRIVER::readPorflowConnectivityFile(bool hybride,const string & connecFileName,_intermediateMED & medi,std::vector<std::set<_maille>::iterator>& p_ma_table,int mesh_dimension)
260 {
261
262     ifstream connFile(connecFileName.c_str(), ios::in);
263     if(!connFile)
264     {
265         string diagnosis("PORFLOW_MESH_RDONLY_DRIVER::read()\nError, can't open connectivity file :");
266         diagnosis+=connecFileName;
267         throw MEDEXCEPTION(diagnosis.c_str());
268     }
269
270     _maille maille;
271     unsigned int code, nodes_number, node;
272     pair<set<_maille>::iterator,bool> p_ma;
273
274     if (hybride) // "HYBR" key-word
275       while (connFile)
276         {
277           connFile >> maille.ordre;
278           if (!connFile) // for spaces at the end of the file
279             break;
280           connFile >> code;
281           connFile >> nodes_number;
282           maille.geometricType = geomPORFLOWtoMED[code-1];
283           if(maille.geometricType%100!=nodes_number) // following incohenrences founded in some porflow files!
284           {
285               MESSAGE("WARNING : the read node number don't seem to be compatible with geometric type!");
286               SCRUTE(maille.geometricType);
287               SCRUTE(nodes_number);
288           }
289           maille.sommets.resize(nodes_number);
290           for (unsigned i=0; i!=nodes_number; ++i)
291             {
292               connFile >> node;
293               maille.sommets[numPORFLOWtoMED[code-1][i]-1] = medi.points.find(node);
294             }
295           p_ma = medi.maillage.insert(maille);
296           if (maille.ordre > p_ma_table.size()-1) // construction of a vector of iterators on _maille structures
297             p_ma_table.resize(2*maille.ordre);
298           p_ma_table[maille.ordre] = p_ma.first;
299         }
300     else // default case (or "VERT" key-word)
301       {
302         if (mesh_dimension == 2) // we have QUA4
303           {
304             code = 2;
305             maille.geometricType = geomPORFLOWtoMED[code-1];
306             nodes_number = 4;
307             maille.sommets.resize(nodes_number);
308           }
309         else if (mesh_dimension == 3) // we have HEXA8
310           {
311             code = 6;
312             maille.geometricType = geomPORFLOWtoMED[code-1];
313             nodes_number = 8;
314             maille.sommets.resize(nodes_number);
315           }
316         else
317           throw MEDEXCEPTION("PORFLOW_MESH_RDONLY_DRIVER::read()\nError, can't determine geometric type for this VERT mesh");
318         while (connFile)
319           {
320             connFile >> maille.ordre;
321             if (!connFile) // for spaces at the end of the file
322               break;
323             for (unsigned i=0; i!=nodes_number; ++i)
324               {
325                 connFile >> node;
326                 maille.sommets[numPORFLOWtoMED[code-1][i]-1] = medi.points.find(node);
327               }
328             p_ma = medi.maillage.insert(maille);
329             if (maille.ordre > p_ma_table.size()-1) // construction of a vector of iterators on _maille structures
330               p_ma_table.resize(2*maille.ordre);
331             p_ma_table[maille.ordre] = p_ma.first;
332           }
333       }
334     connFile.close();
335 }
336
337 void PORFLOW_MESH_RDONLY_DRIVER::read(void)
338   throw (MEDEXCEPTION)
339 {
340     const char * LOC = "PORFLOW_MESH_RDONLY_DRIVER::read() : " ;
341     BEGIN_OF(LOC);
342
343     if (_status!=MED_OPENED)
344         throw MEDEXCEPTION(LOCALIZED(STRING(LOC) << "The _idt of file " << _fileName 
345                     << " is : "  <<  " (the file is not opened)." )) ;
346
347     // if _fileName contains a directory, extract the directory name
348     // the directory name will be used to locate the files included in _fileName.
349     string dirName;
350     string::size_type pos=_fileName.rfind('/');
351     if (pos != string::npos )
352         dirName=string(_fileName, 0, pos+1);
353
354     _intermediateMED medi; // structure de données intermédiaire pour conversion porflow->med
355     string buf_ligne; // pour lire une ligne
356     unsigned numberOfGridElement=0; // number of grid elements
357     unsigned space_dimension=2;  // by default, the problem is assumed to be 2D
358     string coordinateSystem="CARTESIAN";
359     bool hybride=false;
360     _groupe currentGroup;
361     vector<bool> isGroupAList; // vector to store the type of a group (ie PAIR or LIST)
362     bool processLoca=false;
363     string connFileName;
364     string coorFileName;
365     std::vector<std::set<_maille>::iterator> p_ma_table(10000); // store iterators for direct access by index
366     string small("abcdefghijklmnopqrstuvwxyz");
367
368     while ( getline(_porflow, buf_ligne) ) // scan .inp file and look for main keywords (LOCA, GRID, COOR & CONN)
369     {
370
371         // Skip comments
372         if(buf_ligne[0]=='/')
373             continue; 
374         
375         // look if there is a filename
376         string::size_type pos1=string::npos;
377         string::size_type pos2=string::npos;
378         locateFileName(buf_ligne, pos1, pos2);
379         
380         pos=0;
381         if (pos1!=string::npos && pos2!=string::npos) // if there is a file name in buf_line
382             // convert every char to upper, except those between pos1-pos2 (which correspond to a file name)
383             while ( (pos=buf_ligne.find_first_of(small,pos)) != string::npos )
384                 if (pos<pos1 || pos>pos2 )
385                     buf_ligne[pos]=toupper(buf_ligne[pos]);
386                 else
387                     ++pos;
388         else
389             // convert every char to upper
390             while ( (pos=buf_ligne.find_first_of(small,pos)) != string::npos )
391                 buf_ligne[pos]=toupper(buf_ligne[pos]);
392
393         
394         // LOCA KEYWORD :
395         //   expected syntax : 
396         //      - LOCA {PAIR} [ID=id] {N1,N2, ... ,Nn} : group specification by paired element & surface numbers
397         //      - LOCA {LIST} [ID=id] {N1, ... ,Nn}    : group specification by a list of elements
398         //   the syntax corresponding to the use of input file is not implemented
399         if ( isKeyWord(buf_ligne,"LOCA") )
400         {
401             MESSAGE("Mot clé LOCA détecté");
402             processLoca=true;
403             // if currentGroup is not empty, a group has been precessed 
404             //  -> we store it, clear currentGroup, and start the precessing of a new group
405             if ( !currentGroup.groupes.empty() )
406                 medi.groupes.push_back(currentGroup);
407             currentGroup.groupes.clear();
408             currentGroup.nom.erase();
409             if ( buf_ligne.find("PAIR",0) != string::npos )
410             {
411                 isGroupAList.push_back(false);
412             }
413             else if ( buf_ligne.find("LIST",0) != string::npos )
414             {
415                 isGroupAList.push_back(true);
416             }
417             else
418                 throw MEDEXCEPTION("PORFLOW_MESH_RDONLY_DRIVER::read() : Error, after keyword LOCA, LIST or PAIR is expected\n");
419                 
420             pos=buf_ligne.find("ID=",0);
421             if ( pos != string::npos )
422             {
423                 istringstream buf(buf_ligne.c_str()+pos+3);
424                 buf >> currentGroup.nom;
425
426                 // avoid problem in the following processing of elements if the group's name contains a digit
427                 // -> we replace group's name with blanks
428                 while( pos<buf_ligne.size() && !isspace( buf_ligne[pos] ) )
429                     buf_ligne[pos++]=' ';
430             }
431         }
432
433
434         // GRID KEYWORD :
435         //   expected syntax : GRID {UNST} [THREE] {N1} [NODE] [N2]
436         //   the syntax corresponding to structured grids is not implemented
437         else if ( isKeyWord(buf_ligne,"GRID") )
438         {
439             MESSAGE("Mot clé GRID détecté");
440             processLoca=false;
441             pos=buf_ligne.find("UNST",0);
442             if ( pos != string::npos ) // unstructured grid
443             {
444                 // we find the number of grid elements
445                 string::size_type len=buf_ligne.size();
446                 while ( pos<len && !isdigit(buf_ligne[pos]) )
447                         ++pos;
448                 if ( pos==len )
449                     throw MEDEXCEPTION("PORFLOW_MESH_RDONLY_DRIVER::read() : Error, number of grid elements unspecified!\n");
450                 istringstream buf(buf_ligne.c_str()+pos);
451                 buf >> numberOfGridElement;
452
453                 pos=buf_ligne.find("THREE",0);
454                 if ( pos != string::npos ) // if we find THREE, the problem is 3D
455                     space_dimension=3;
456             }
457             else
458             {
459                 throw MEDEXCEPTION("PORFLOW_MESH_RDONLY_DRIVER::read() : Error, structured grids are not yet supported!\n");
460             }
461         }
462         
463
464         // CONN KEYWORD :
465         //   expected syntax : 
466         //      - CONN {HYBR} {filename} : vertex connectivity for mixed hybrid elements
467         //      - CONN {VERT} {filename} : vertex connectivity for quad or hex elements
468         //   the default option is HYBR
469         else if ( isKeyWord(buf_ligne,"CONN") )
470         {
471             MESSAGE("Mot clé CONN détecté");
472             processLoca=false;
473             string fileCONN=getPorflowFileName(buf_ligne,"CONN");
474             
475             if ( buf_ligne.find("HYBR",0) != string::npos )
476                 hybride=true;
477
478
479             if(fileCONN.rfind('/') == string::npos)
480                 // no directory was specified -> we add dirName, which may be empty
481                 connFileName=dirName+fileCONN;
482             else
483                 connFileName=fileCONN;
484         }
485
486         
487         // COOR KEYWORD :
488         //   expected syntax : COOR {VERT} {filename}
489         else if ( isKeyWord(buf_ligne,"COOR") )
490         {
491             MESSAGE("Mot clé COOR détecté");
492             processLoca=false;
493             string fileCOOR=getPorflowFileName(buf_ligne,"COOR");
494
495             pos=buf_ligne.find("VERT",0);
496             if ( pos == string::npos ) 
497                 throw MEDEXCEPTION("PORFLOW_MESH_RDONLY_DRIVER::read() : Error, after keyword COOR, we require VERT\n");
498
499             pos=buf_ligne.find("CYLI",0);
500             if ( pos != string::npos )
501                 coordinateSystem="CYLINDRICAL";
502
503             if(fileCOOR.rfind('/') == string::npos)
504                 // no directory was specified -> we add dirName, which may be empty
505                 coorFileName=dirName+fileCOOR;
506             else
507                 coorFileName=fileCOOR;
508         }
509
510
511         if (processLoca) 
512         {
513             // read group specification
514
515
516             // replace non digit caracters with blanks
517             string::iterator last_non_blank=buf_ligne.end();
518             for (string::iterator it=buf_ligne.begin(); it!=buf_ligne.end(); ++it)
519                 if ( !isdigit(*it) )
520                     *it=' ';
521                 else
522                     last_non_blank=it;
523
524             if (last_non_blank != buf_ligne.end() ) // if the line is not blank
525             {
526                 buf_ligne=string(buf_ligne.begin(),++last_non_blank); // suppress trailing blanks
527
528                 istringstream buf(buf_ligne.c_str());
529                 int i1;
530                 buf >> i1; // we know the line is not blank
531                 do
532                 {
533                     currentGroup.groupes.push_back(i1);
534                     buf >> i1;
535                 }
536                 while ( buf );
537
538             }
539         }
540         
541     }
542     if ( !currentGroup.groupes.empty() ) // if necessary, add the last group to medi.groupes
543         medi.groupes.push_back(currentGroup);
544
545     readPorflowCoordinateFile(coorFileName,medi,space_dimension);
546     readPorflowConnectivityFile(hybride,connFileName,medi,p_ma_table,space_dimension);
547
548
549     // Group processing :
550     //   In the scan loop, we have store in medi.groupes.groupes either :
551     //     - paired list of element and surface number (keyword PAIR)
552     //     - an explicit list of element numbers (keyword LIST)
553     //   What we stored (pairs or list) is remembered through vector isGroupAList.
554     //   For both cases, we must convert these numbers to iterators to cells inside the set medi.maillage
555     //     - in the LIST case, these cells already exist.
556     //     - in the PAIR case, we have to create the corresponding 2D/1D faces
557     // scan groups
558     //for( std::vector<_groupe>::iterator i=medi.groupes.begin(); i!=medi.groupes.end(); ++i)
559     for( int i=0; i!=medi.groupes.size(); ++i)
560     {
561         if ( isGroupAList[i] ) 
562         {
563             // medi.groupes[i].groupes is a vector of element numbers; it points to it
564             std::vector<int>::const_iterator it=medi.groupes[i].groupes.begin();
565             for(  ; it!=medi.groupes[i].groupes.end(); ++it)
566             {
567                 // insert the iterator to the corresponding cell we stored in p_ma_table
568                 medi.groupes[i].mailles.insert( p_ma_table[*it] );
569             }
570             
571         }
572         else
573         {
574             int nelem=0;
575             int nface=0;
576             int ngeom=0;
577             std::set<_maille>::iterator p_ma;
578             _maille maille2D;
579             
580             // medi.groupes[i].groupes is a vector of paired element and surface numbers
581             // *it points to the element number,  *(it+1) points to the surface number
582             std::vector<int>::const_iterator it=medi.groupes[i].groupes.begin();
583             for(  ; it!=medi.groupes[i].groupes.end(); ++it)
584             {
585                 nelem=*it;
586                 nface=*(++it);
587                 p_ma=p_ma_table[nelem]; // points to the cell
588                 ngeom=geomMEDtoPorflow(p_ma->geometricType);
589
590                 // create the face corresponding to nface
591                 int l=0;
592                 while( l<nb_nodes2_max && connectivityPORFLOW[ngeom][nface-1][l] )
593                 {
594                     maille2D.sommets.push_back(p_ma->sommets[ numPORFLOWtoMED[ngeom][ connectivityPORFLOW[ngeom][nface-1][l++]-1 ]-1 ]);
595                 }
596
597                 // the corresponding 2D MED geometric type depends upon the number of nodes
598                 maille2D.sommets.resize(l);
599                 maille2D.geometricType = get2DMedGeomType(l);
600                 p_ma = medi.maillage.insert(maille2D).first; // we insert the face in our mesh
601                 medi.groupes[i].mailles.insert(p_ma); // and insert an iterator on it in our group
602                 maille2D.sommets.clear();
603             }
604
605         }
606         // medi.groupes[i].groupes.clear(); // we don't need element numbers anymore
607         
608     }
609
610     p_ma_table.clear(); // we don't need it anymore
611     MESSAGE(LOC << "GIBI_MESH_RDONLY_DRIVER::read : RESULTATS STRUCTURE INTERMEDIAIRES : ");
612     MESSAGE(LOC <<  medi );
613             // TRANSFORMATION EN STRUCTURES MED
614     if ( ! _ptrMesh->isEmpty() )
615     {
616         throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Mesh object not empty : can't fill it!"));
617     }
618     else if ( medi.maillage.size()==0 || medi.groupes.size()==0 || medi.points.size()==0)
619     {
620         throw MEDEXCEPTION(LOCALIZED(STRING(LOC) << " Error while reading file " << _fileName 
621                     << " The data read are not completed " ) ) ;
622     }
623     else
624     {
625         _ptrMesh->_name = _meshName;
626         _ptrMesh->_spaceDimension = medi.points.begin()->second.coord.size();
627         _ptrMesh->_meshDimension = medi.maillage.rbegin()->dimension();
628         _ptrMesh->_numberOfNodes = medi.points.size();
629         _ptrMesh->_isAGrid = 0;
630         _ptrMesh->_coordinate = medi.getCoordinate();
631
632         //Construction des groupes
633         vector<GROUP *> groupCell, groupFace, groupEdge, groupNode;
634         medi.getGroups(groupCell, groupFace, groupEdge, groupNode, _ptrMesh);
635         _ptrMesh->_groupCell = groupCell;
636         _ptrMesh->_groupFace = groupFace;
637         _ptrMesh->_groupEdge = groupEdge;
638         _ptrMesh->_groupNode = groupNode;
639
640         // appele en dernier car cette fonction detruit le maillage intermediaire!
641         _ptrMesh->_connectivity = medi.getConnectivity(); 
642         MESSAGE(LOC << "GIBI_MESH_RDONLY_DRIVER::read : FIN ");
643
644         // calcul de la connectivite d-1 complete, avec renumerotation des groupes
645         // if (_ptrMesh->_spaceDimension==3)
646         //     _ptrMesh->_connectivity->updateGroup(_ptrMesh->_groupFace) ;
647         // else if (_ptrMesh->_spaceDimension==2)
648         //     _ptrMesh->_connectivity->updateGroup(_ptrMesh->_groupEdge) ;
649         
650         // Creation des familles à partir des groupes
651         // NC : Cet appel pourra être différé quand la gestion de la cohérence famille/groupes sera assurée
652         _ptrMesh->createFamilies();
653     }
654
655
656     END_OF(LOC);
657 }
658
659 void PORFLOW_MESH_RDONLY_DRIVER::write( void ) const
660   throw (MEDEXCEPTION)
661 {
662   throw MEDEXCEPTION("PORFLOW_MESH_RDONLY_DRIVER::write : Can't write with a RDONLY driver !");
663 }
664
665
666 /*--------------------- WRONLY PART -------------------------------*/
667
668 PORFLOW_MESH_WRONLY_DRIVER::PORFLOW_MESH_WRONLY_DRIVER():PORFLOW_MESH_DRIVER()
669 {
670 }
671   
672 PORFLOW_MESH_WRONLY_DRIVER::PORFLOW_MESH_WRONLY_DRIVER(const string & fileName,
673                                                  MESH * ptrMesh):
674   PORFLOW_MESH_DRIVER(fileName,ptrMesh,MED_WRONLY)
675 {
676   MESSAGE("PORFLOW_MESH_WRONLY_DRIVER::PORFLOW_MESH_WRONLY_DRIVER(const string & fileName, MESH * ptrMesh) has been created");
677 }
678
679 PORFLOW_MESH_WRONLY_DRIVER::PORFLOW_MESH_WRONLY_DRIVER(const PORFLOW_MESH_WRONLY_DRIVER & driver): 
680   PORFLOW_MESH_DRIVER(driver)
681 {
682 }
683
684 PORFLOW_MESH_WRONLY_DRIVER::~PORFLOW_MESH_WRONLY_DRIVER()
685 {
686   //MESSAGE("PORFLOW_MESH_WRONLY_DRIVER::PORFLOW_MESH_WRONLY_DRIVER(const string & fileName, MESH * ptrMesh) has been destroyed");
687 }
688
689 GENDRIVER * PORFLOW_MESH_WRONLY_DRIVER::copy(void) const
690 {
691   return new PORFLOW_MESH_WRONLY_DRIVER(*this);
692 }
693
694 void PORFLOW_MESH_WRONLY_DRIVER::read (void)
695   throw (MEDEXCEPTION)
696 {
697   throw MEDEXCEPTION("PORFLOW_MESH_WRONLY_DRIVER::read : Can't read with a WRONLY driver !");
698 }
699
700 void PORFLOW_MESH_WRONLY_DRIVER::write(void) const
701   throw (MEDEXCEPTION)
702
703   const char * LOC = "void PORFLOW_MESH_WRONLY_DRIVER::write(void) const : ";
704   BEGIN_OF(LOC);
705
706   throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<< "Write Driver isn\'t implemented"));
707
708   END_OF(LOC);
709
710
711
712
713 /*--------------------- RDWR PART -------------------------------*/
714
715 PORFLOW_MESH_RDWR_DRIVER::PORFLOW_MESH_RDWR_DRIVER():PORFLOW_MESH_DRIVER()
716 {
717 }
718
719 PORFLOW_MESH_RDWR_DRIVER::PORFLOW_MESH_RDWR_DRIVER(const string & fileName,
720                                            MESH * ptrMesh):
721   PORFLOW_MESH_DRIVER(fileName,ptrMesh,MED_RDWR)
722 {
723   MESSAGE("PORFLOW_MESH_RDWR_DRIVER::PORFLOW_MESH_RDWR_DRIVER(const string & fileName, MESH * ptrMesh) has been created");
724 }
725
726 PORFLOW_MESH_RDWR_DRIVER::PORFLOW_MESH_RDWR_DRIVER(const PORFLOW_MESH_RDWR_DRIVER & driver): 
727   PORFLOW_MESH_RDONLY_DRIVER::PORFLOW_MESH_DRIVER(driver)
728 {
729 }
730
731 PORFLOW_MESH_RDWR_DRIVER::~PORFLOW_MESH_RDWR_DRIVER() {
732   //MESSAGE("PORFLOW_MESH_RDWR_DRIVER::PORFLOW_MESH_RDWR_DRIVER(const string & fileName, MESH * ptrMesh) has been destroyed");
733
734   
735 GENDRIVER * PORFLOW_MESH_RDWR_DRIVER::copy(void) const
736 {
737   return new PORFLOW_MESH_RDWR_DRIVER(*this);
738 }
739
740 void PORFLOW_MESH_RDWR_DRIVER::write(void) const
741   throw (MEDEXCEPTION)
742 {
743   PORFLOW_MESH_WRONLY_DRIVER::write();
744 }
745 void PORFLOW_MESH_RDWR_DRIVER::read (void)
746   throw (MEDEXCEPTION)
747 {
748   PORFLOW_MESH_RDONLY_DRIVER::read();
749 }