Salome HOME
update after merging trhe branches CEA_V3_0_x, OCC_V3_1_0_a1_x, and the main
[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     return MED_NONE;
208 }
209
210 // helper function to read a porflow file name (enclosed in single or double quotes) in line
211 inline static string getPorflowFileName(const string& line, const char * context)
212 {
213     string::size_type pos1=string::npos;
214     string::size_type pos2=string::npos;
215
216     locateFileName(line, pos1, pos2);
217
218     // if we found a not empty filename
219     if (pos1 != string::npos && pos2 != string::npos && pos2>pos1+1)
220         return string(line,pos1+1,pos2-pos1-1);
221
222     // else, we throw an exception
223     string diagnosis("PORFLOW_MESH_RDONLY_DRIVER::read() : Error after reading keyword ");
224     diagnosis+=context;
225     diagnosis+="\nNo filename was found enclosed in single or double quotes\n";
226     throw MEDEXCEPTION(diagnosis.c_str());
227 }
228
229
230 // helper function to read a porflow coordinate file ( .xyz )
231 void PORFLOW_MESH_RDONLY_DRIVER::readPorflowCoordinateFile(const string & coorFileName,_intermediateMED & medi,const int space_dimension)
232 {
233
234     ifstream coorFile(coorFileName.c_str(), ios::in);
235     if(!coorFile)
236     {
237         string diagnosis("PORFLOW_MESH_RDONLY_DRIVER::read()\nError, can't open coordinates file :");
238         diagnosis+=coorFileName;
239         throw MEDEXCEPTION(diagnosis.c_str());
240     }
241     
242     // scan of the coord file
243     _noeud node;
244     node.coord.resize(space_dimension);
245     string buf_ligne; // to read a line
246     while ( getline(coorFile, buf_ligne) ) // we can't use input stream directly because some 2D files have "0.0" in third coordinate
247       {
248         istringstream buf(buf_ligne.c_str());
249         buf >> node.number;
250         if (!buf) // for spaces at the end of the file
251           break;
252         for (unsigned i=0; i!=space_dimension; ++i)
253           buf >> node.coord[i];
254         medi.points.insert(make_pair(node.number,node));
255       }
256     coorFile.close();
257 }
258
259 // helper function to read a porflow connectivity file ( .cnc )
260 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)
261 {
262
263     ifstream connFile(connecFileName.c_str(), ios::in);
264     if(!connFile)
265     {
266         string diagnosis("PORFLOW_MESH_RDONLY_DRIVER::read()\nError, can't open connectivity file :");
267         diagnosis+=connecFileName;
268         throw MEDEXCEPTION(diagnosis.c_str());
269     }
270
271     _maille maille;
272     unsigned int code, nodes_number, node;
273     pair<set<_maille>::iterator,bool> p_ma;
274
275     if (hybride) // "HYBR" key-word
276       while (connFile)
277         {
278           connFile >> maille.ordre;
279           if (!connFile) // for spaces at the end of the file
280             break;
281           connFile >> code;
282           connFile >> nodes_number;
283           maille.geometricType = geomPORFLOWtoMED[code-1];
284           if(maille.geometricType%100!=nodes_number) // following incohenrences founded in some porflow files!
285           {
286               MESSAGE("WARNING : the read node number don't seem to be compatible with geometric type!");
287               SCRUTE(maille.geometricType);
288               SCRUTE(nodes_number);
289           }
290           maille.sommets.resize(nodes_number);
291           for (unsigned i=0; i!=nodes_number; ++i)
292             {
293               connFile >> node;
294               maille.sommets[numPORFLOWtoMED[code-1][i]-1] = medi.points.find(node);
295             }
296           p_ma = medi.maillage.insert(maille);
297           if (maille.ordre > p_ma_table.size()-1) // construction of a vector of iterators on _maille structures
298             p_ma_table.resize(2*maille.ordre);
299           p_ma_table[maille.ordre] = p_ma.first;
300         }
301     else // default case (or "VERT" key-word)
302       {
303         if (mesh_dimension == 2) // we have QUA4
304           {
305             code = 2;
306             maille.geometricType = geomPORFLOWtoMED[code-1];
307             nodes_number = 4;
308             maille.sommets.resize(nodes_number);
309           }
310         else if (mesh_dimension == 3) // we have HEXA8
311           {
312             code = 6;
313             maille.geometricType = geomPORFLOWtoMED[code-1];
314             nodes_number = 8;
315             maille.sommets.resize(nodes_number);
316           }
317         else
318           throw MEDEXCEPTION("PORFLOW_MESH_RDONLY_DRIVER::read()\nError, can't determine geometric type for this VERT mesh");
319         while (connFile)
320           {
321             connFile >> maille.ordre;
322             if (!connFile) // for spaces at the end of the file
323               break;
324             for (unsigned i=0; i!=nodes_number; ++i)
325               {
326                 connFile >> node;
327                 maille.sommets[numPORFLOWtoMED[code-1][i]-1] = medi.points.find(node);
328               }
329             p_ma = medi.maillage.insert(maille);
330             if (maille.ordre > p_ma_table.size()-1) // construction of a vector of iterators on _maille structures
331               p_ma_table.resize(2*maille.ordre);
332             p_ma_table[maille.ordre] = p_ma.first;
333           }
334       }
335     connFile.close();
336 }
337
338 void PORFLOW_MESH_RDONLY_DRIVER::read(void)
339   throw (MEDEXCEPTION)
340 {
341     const char * LOC = "PORFLOW_MESH_RDONLY_DRIVER::read() : " ;
342     BEGIN_OF(LOC);
343
344     if (_status!=MED_OPENED)
345         throw MEDEXCEPTION(LOCALIZED(STRING(LOC) << "The _idt of file " << _fileName 
346                     << " is : "  <<  " (the file is not opened)." )) ;
347
348     // if _fileName contains a directory, extract the directory name
349     // the directory name will be used to locate the files included in _fileName.
350     string dirName;
351     string::size_type pos=_fileName.rfind('/');
352     if (pos != string::npos )
353         dirName=string(_fileName, 0, pos+1);
354
355     _intermediateMED medi; // structure de données intermédiaire pour conversion porflow->med
356     string buf_ligne; // pour lire une ligne
357     unsigned numberOfGridElement=0; // number of grid elements
358     unsigned space_dimension=2;  // by default, the problem is assumed to be 2D
359     string coordinateSystem="CARTESIAN";
360     bool hybride=false;
361     _groupe currentGroup;
362     vector<bool> isGroupAList; // vector to store the type of a group (ie PAIR or LIST)
363     bool processLoca=false;
364     string connFileName;
365     string coorFileName;
366     std::vector<std::set<_maille>::iterator> p_ma_table(10000); // store iterators for direct access by index
367     string small("abcdefghijklmnopqrstuvwxyz");
368
369     while ( getline(_porflow, buf_ligne) ) // scan .inp file and look for main keywords (LOCA, GRID, COOR & CONN)
370     {
371
372         // Skip comments
373         if(buf_ligne[0]=='/')
374             continue; 
375         
376         // look if there is a filename
377         string::size_type pos1=string::npos;
378         string::size_type pos2=string::npos;
379         locateFileName(buf_ligne, pos1, pos2);
380         
381         pos=0;
382         if (pos1!=string::npos && pos2!=string::npos) // if there is a file name in buf_line
383             // convert every char to upper, except those between pos1-pos2 (which correspond to a file name)
384             while ( (pos=buf_ligne.find_first_of(small,pos)) != string::npos )
385                 if (pos<pos1 || pos>pos2 )
386                     buf_ligne[pos]=toupper(buf_ligne[pos]);
387                 else
388                     ++pos;
389         else
390             // convert every char to upper
391             while ( (pos=buf_ligne.find_first_of(small,pos)) != string::npos )
392                 buf_ligne[pos]=toupper(buf_ligne[pos]);
393
394         
395         // LOCA KEYWORD :
396         //   expected syntax : 
397         //      - LOCA {PAIR} [ID=id] {N1,N2, ... ,Nn} : group specification by paired element & surface numbers
398         //      - LOCA {LIST} [ID=id] {N1, ... ,Nn}    : group specification by a list of elements
399         //   the syntax corresponding to the use of input file is not implemented
400         if ( isKeyWord(buf_ligne,"LOCA") )
401         {
402             MESSAGE("Mot clé LOCA détecté");
403             processLoca=true;
404             // if currentGroup is not empty, a group has been precessed 
405             //  -> we store it, clear currentGroup, and start the precessing of a new group
406             if ( !currentGroup.groupes.empty() )
407                 medi.groupes.push_back(currentGroup);
408             currentGroup.groupes.clear();
409             currentGroup.nom.erase();
410             if ( buf_ligne.find("PAIR",0) != string::npos )
411             {
412                 isGroupAList.push_back(false);
413             }
414             else if ( buf_ligne.find("LIST",0) != string::npos )
415             {
416                 isGroupAList.push_back(true);
417             }
418             else
419                 throw MEDEXCEPTION("PORFLOW_MESH_RDONLY_DRIVER::read() : Error, after keyword LOCA, LIST or PAIR is expected\n");
420                 
421             pos=buf_ligne.find("ID=",0);
422             if ( pos != string::npos )
423             {
424                 istringstream buf(buf_ligne.c_str()+pos+3);
425                 buf >> currentGroup.nom;
426
427                 // avoid problem in the following processing of elements if the group's name contains a digit
428                 // -> we replace group's name with blanks
429                 while( pos<buf_ligne.size() && !isspace( buf_ligne[pos] ) )
430                     buf_ligne[pos++]=' ';
431             }
432         }
433
434
435         // GRID KEYWORD :
436         //   expected syntax : GRID {UNST} [THREE] {N1} [NODE] [N2]
437         //   the syntax corresponding to structured grids is not implemented
438         else if ( isKeyWord(buf_ligne,"GRID") )
439         {
440             MESSAGE("Mot clé GRID détecté");
441             processLoca=false;
442             pos=buf_ligne.find("UNST",0);
443             if ( pos != string::npos ) // unstructured grid
444             {
445                 // we find the number of grid elements
446                 string::size_type len=buf_ligne.size();
447                 while ( pos<len && !isdigit(buf_ligne[pos]) )
448                         ++pos;
449                 if ( pos==len )
450                     throw MEDEXCEPTION("PORFLOW_MESH_RDONLY_DRIVER::read() : Error, number of grid elements unspecified!\n");
451                 istringstream buf(buf_ligne.c_str()+pos);
452                 buf >> numberOfGridElement;
453
454                 pos=buf_ligne.find("THREE",0);
455                 if ( pos != string::npos ) // if we find THREE, the problem is 3D
456                     space_dimension=3;
457             }
458             else
459             {
460                 throw MEDEXCEPTION("PORFLOW_MESH_RDONLY_DRIVER::read() : Error, structured grids are not yet supported!\n");
461             }
462         }
463         
464
465         // CONN KEYWORD :
466         //   expected syntax : 
467         //      - CONN {HYBR} {filename} : vertex connectivity for mixed hybrid elements
468         //      - CONN {VERT} {filename} : vertex connectivity for quad or hex elements
469         //   the default option is HYBR
470         else if ( isKeyWord(buf_ligne,"CONN") )
471         {
472             MESSAGE("Mot clé CONN détecté");
473             processLoca=false;
474             string fileCONN=getPorflowFileName(buf_ligne,"CONN");
475             
476             if ( buf_ligne.find("HYBR",0) != string::npos )
477                 hybride=true;
478
479
480             if(fileCONN.rfind('/') == string::npos)
481                 // no directory was specified -> we add dirName, which may be empty
482
483                 connFileName=dirName+fileCONN;
484             else
485                 connFileName=fileCONN;
486         }
487
488         
489         // COOR KEYWORD :
490         //   expected syntax : COOR {VERT} {filename}
491         else if ( isKeyWord(buf_ligne,"COOR") )
492         {
493             MESSAGE("Mot clé COOR");
494             processLoca=false;
495             string fileCOOR=getPorflowFileName(buf_ligne,"COOR");
496
497             pos=buf_ligne.find("VERT",0);
498             if ( pos == string::npos ) 
499                 throw MEDEXCEPTION("PORFLOW_MESH_RDONLY_DRIVER::read() : Error, after keyword COOR, we require VERT\n");
500
501             pos=buf_ligne.find("CYLI",0);
502             if ( pos != string::npos )
503                 coordinateSystem="CYLINDRICAL";
504
505             if(fileCOOR.rfind('/') == string::npos)
506                 // no directory was specified -> we add dirName, which may be empty
507                 coorFileName=dirName+fileCOOR;
508             else
509                 coorFileName=fileCOOR;
510         }
511
512
513         if (processLoca) 
514         {
515             // read group specification
516
517
518             // replace non digit caracters with blanks
519             string::iterator last_non_blank=buf_ligne.end();
520             for (string::iterator it=buf_ligne.begin(); it!=buf_ligne.end(); ++it)
521                 if ( !isdigit(*it) )
522                     *it=' ';
523                 else
524                     last_non_blank=it;
525
526             if (last_non_blank != buf_ligne.end() ) // if the line is not blank
527             {
528                 buf_ligne=string(buf_ligne.begin(),++last_non_blank); // suppress trailing blanks
529
530                 istringstream buf(buf_ligne.c_str());
531                 int i1;
532                 buf >> i1; // we know the line is not blank
533                 do
534                 {
535                     currentGroup.groupes.push_back(i1);
536                     buf >> i1;
537                 }
538                 while ( buf );
539
540             }
541         }
542         
543     }
544     if ( !currentGroup.groupes.empty() ) // if necessary, add the last group to medi.groupes
545         medi.groupes.push_back(currentGroup);
546
547     readPorflowCoordinateFile(coorFileName,medi,space_dimension);
548     readPorflowConnectivityFile(hybride,connFileName,medi,p_ma_table,space_dimension);
549
550
551     // Group processing :
552     //   In the scan loop, we have store in medi.groupes.groupes either :
553     //     - paired list of element and surface number (keyword PAIR)
554     //     - an explicit list of element numbers (keyword LIST)
555     //   What we stored (pairs or list) is remembered through vector isGroupAList.
556     //   For both cases, we must convert these numbers to iterators to cells inside the set medi.maillage
557     //     - in the LIST case, these cells already exist.
558     //     - in the PAIR case, we have to create the corresponding 2D/1D faces
559     // scan groups
560     //for( std::vector<_groupe>::iterator i=medi.groupes.begin(); i!=medi.groupes.end(); ++i)
561     for( int i=0; i!=medi.groupes.size(); ++i)
562     {
563         if ( isGroupAList[i] ) 
564         {
565             // medi.groupes[i].groupes is a vector of element numbers; it points to it
566             medi.groupes[i].mailles.resize( medi.groupes[i].groupes.size() );
567             std::vector<int>::const_iterator it=medi.groupes[i].groupes.begin();
568             for(int j = 0 ; it!=medi.groupes[i].groupes.end(); ++it, ++j)
569             {
570                 // insert the iterator to the corresponding cell we stored in p_ma_table
571                 medi.groupes[i].mailles[j] = p_ma_table[*it];
572             }
573             
574         }
575         else
576         {
577             int nelem=0;
578             int nface=0;
579             int ngeom=0;
580             int ielem=0;
581             std::set<_maille>::iterator p_ma;
582             _maille maille2D;
583             
584             // medi.groupes[i].groupes is a vector of paired element and surface numbers
585             // *it points to the element number,  *(it+1) points to the surface number
586             std::vector<int>::const_iterator it=medi.groupes[i].groupes.begin();
587             medi.groupes[i].mailles.resize( medi.groupes[i].groupes.size() / 2 );
588             for(  ; it!=medi.groupes[i].groupes.end(); ++it)
589             {
590                 nelem=*it;
591                 nface=*(++it);
592                 p_ma=p_ma_table[nelem]; // points to the cell
593                 ngeom=geomMEDtoPorflow(p_ma->geometricType);
594
595                 // create the face corresponding to nface
596                 int l=0;
597                 while( l<nb_nodes2_max && connectivityPORFLOW[ngeom][nface-1][l] )
598                 {
599                     maille2D.sommets.push_back(p_ma->sommets[ numPORFLOWtoMED[ngeom][ connectivityPORFLOW[ngeom][nface-1][l++]-1 ]-1 ]);
600                 }
601
602                 // the corresponding 2D MED geometric type depends upon the number of nodes
603                 maille2D.sommets.resize(l);
604                 maille2D.geometricType = get2DMedGeomType(l);
605                 p_ma = medi.maillage.insert(maille2D).first; // we insert the face in our mesh
606                 medi.groupes[i].mailles[ielem++]=p_ma; // and insert an iterator on it in our group
607                 maille2D.sommets.clear();
608             }
609
610         }
611         medi.groupes[i].groupes.clear(); // we don't need element numbers anymore
612         
613     }
614
615     p_ma_table.clear(); // we don't need it anymore
616     MESSAGE(LOC << "PORFLOW_MESH_RDONLY_DRIVER::read : RESULTATS STRUCTURE INTERMEDIAIRES : ");
617     MESSAGE(LOC <<  medi );
618             // TRANSFORMATION EN STRUCTURES MED
619     if ( ! _ptrMesh->isEmpty() )
620     {
621         throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Mesh object not empty : can't fill it!"));
622     }
623     else if ( medi.maillage.size()==0 || medi.groupes.size()==0 || medi.points.size()==0)
624     {
625         throw MEDEXCEPTION(LOCALIZED(STRING(LOC) << " Error while reading file " << _fileName 
626                     << " The data read are not completed " ) ) ;
627     }
628     else
629     {
630         _ptrMesh->_name = _meshName;
631         _ptrMesh->_spaceDimension = medi.points.begin()->second.coord.size();
632         _ptrMesh->_meshDimension = medi.maillage.rbegin()->dimension();
633         _ptrMesh->_numberOfNodes = medi.points.size();
634         _ptrMesh->_isAGrid = 0;
635         _ptrMesh->_coordinate = medi.getCoordinate();
636
637         //Construction des groupes
638         vector<GROUP *> groupCell, groupFace, groupEdge, groupNode;
639         medi.getGroups(groupCell, groupFace, groupEdge, groupNode, _ptrMesh);
640         _ptrMesh->_groupCell = groupCell;
641         _ptrMesh->_groupFace = groupFace;
642         _ptrMesh->_groupEdge = groupEdge;
643         _ptrMesh->_groupNode = groupNode;
644
645         // appele en dernier car cette fonction detruit le maillage intermediaire!
646         _ptrMesh->_connectivity = medi.getConnectivity(); 
647         MESSAGE(LOC << "PORFLOW_MESH_RDONLY_DRIVER::read : FIN ");
648
649         // calcul de la connectivite d-1 complete, avec renumerotation des groupes
650         // if (_ptrMesh->_spaceDimension==3)
651         //     _ptrMesh->_connectivity->updateGroup(_ptrMesh->_groupFace) ;
652         // else if (_ptrMesh->_spaceDimension==2)
653         //     _ptrMesh->_connectivity->updateGroup(_ptrMesh->_groupEdge) ;
654         
655         // Creation des familles ?artir des groupes
656         // NC : Cet appel pourra ?e diff鲩 quand la gestion de la coh鲥nce famille/groupes sera assur饊      _ptrMesh->createFamilies();
657     }
658
659
660     END_OF(LOC);
661 }
662
663 void PORFLOW_MESH_RDONLY_DRIVER::write( void ) const
664   throw (MEDEXCEPTION)
665 {
666   throw MEDEXCEPTION("PORFLOW_MESH_RDONLY_DRIVER::write : Can't write with a RDONLY driver !");
667 }
668
669
670 /*--------------------- WRONLY PART -------------------------------*/
671
672 PORFLOW_MESH_WRONLY_DRIVER::PORFLOW_MESH_WRONLY_DRIVER():PORFLOW_MESH_DRIVER()
673 {
674 }
675   
676 PORFLOW_MESH_WRONLY_DRIVER::PORFLOW_MESH_WRONLY_DRIVER(const string & fileName,
677                                                  MESH * ptrMesh):
678   PORFLOW_MESH_DRIVER(fileName,ptrMesh,MED_WRONLY)
679 {
680   MESSAGE("PORFLOW_MESH_WRONLY_DRIVER::PORFLOW_MESH_WRONLY_DRIVER(const string & fileName, MESH * ptrMesh) has been created");
681 }
682
683 PORFLOW_MESH_WRONLY_DRIVER::PORFLOW_MESH_WRONLY_DRIVER(const PORFLOW_MESH_WRONLY_DRIVER & driver): 
684   PORFLOW_MESH_DRIVER(driver)
685 {
686 }
687
688 PORFLOW_MESH_WRONLY_DRIVER::~PORFLOW_MESH_WRONLY_DRIVER()
689 {
690   //MESSAGE("PORFLOW_MESH_WRONLY_DRIVER::PORFLOW_MESH_WRONLY_DRIVER(const string & fileName, MESH * ptrMesh) has been destroyed");
691 }
692
693 GENDRIVER * PORFLOW_MESH_WRONLY_DRIVER::copy(void) const
694 {
695   return new PORFLOW_MESH_WRONLY_DRIVER(*this);
696 }
697
698 void PORFLOW_MESH_WRONLY_DRIVER::read (void)
699   throw (MEDEXCEPTION)
700 {
701   throw MEDEXCEPTION("PORFLOW_MESH_WRONLY_DRIVER::read : Can't read with a WRONLY driver !");
702 }
703
704 void PORFLOW_MESH_WRONLY_DRIVER::write(void) const
705   throw (MEDEXCEPTION)
706
707   const char * LOC = "void PORFLOW_MESH_WRONLY_DRIVER::write(void) const : ";
708   BEGIN_OF(LOC);
709
710   throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<< "Write Driver isn\'t implemented"));
711
712   END_OF(LOC);
713
714
715
716
717 /*--------------------- RDWR PART -------------------------------*/
718
719 PORFLOW_MESH_RDWR_DRIVER::PORFLOW_MESH_RDWR_DRIVER():PORFLOW_MESH_DRIVER()
720 {
721 }
722
723 PORFLOW_MESH_RDWR_DRIVER::PORFLOW_MESH_RDWR_DRIVER(const string & fileName,
724                                            MESH * ptrMesh):
725   PORFLOW_MESH_DRIVER(fileName,ptrMesh,MED_RDWR)
726 {
727   MESSAGE("PORFLOW_MESH_RDWR_DRIVER::PORFLOW_MESH_RDWR_DRIVER(const string & fileName, MESH * ptrMesh) has been created");
728 }
729
730 PORFLOW_MESH_RDWR_DRIVER::PORFLOW_MESH_RDWR_DRIVER(const PORFLOW_MESH_RDWR_DRIVER & driver): 
731   PORFLOW_MESH_RDONLY_DRIVER::PORFLOW_MESH_DRIVER(driver)
732 {
733 }
734
735 PORFLOW_MESH_RDWR_DRIVER::~PORFLOW_MESH_RDWR_DRIVER() {
736   //MESSAGE("PORFLOW_MESH_RDWR_DRIVER::PORFLOW_MESH_RDWR_DRIVER(const string & fileName, MESH * ptrMesh) has been destroyed");
737
738   
739 GENDRIVER * PORFLOW_MESH_RDWR_DRIVER::copy(void) const
740 {
741   return new PORFLOW_MESH_RDWR_DRIVER(*this);
742 }
743
744 void PORFLOW_MESH_RDWR_DRIVER::write(void) const
745   throw (MEDEXCEPTION)
746 {
747   PORFLOW_MESH_WRONLY_DRIVER::write();
748 }
749 void PORFLOW_MESH_RDWR_DRIVER::read (void)
750   throw (MEDEXCEPTION)
751 {
752   PORFLOW_MESH_RDONLY_DRIVER::read();
753 }