]> SALOME platform Git repositories - modules/med.git/blob - src/MEDMEM/MEDMEM_PorflowMeshDriver.cxx
Salome HOME
merging the main trunk with the BrForComp branch to build a pre V3_0_1
[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
482                 connFileName=dirName+fileCONN;
483             else
484                 connFileName=fileCONN;
485         }
486
487         
488         // COOR KEYWORD :
489         //   expected syntax : COOR {VERT} {filename}
490         else if ( isKeyWord(buf_ligne,"COOR") )
491         {
492             MESSAGE("Mot clé COOR");
493             processLoca=false;
494             string fileCOOR=getPorflowFileName(buf_ligne,"COOR");
495
496             pos=buf_ligne.find("VERT",0);
497             if ( pos == string::npos ) 
498                 throw MEDEXCEPTION("PORFLOW_MESH_RDONLY_DRIVER::read() : Error, after keyword COOR, we require VERT\n");
499
500             pos=buf_ligne.find("CYLI",0);
501             if ( pos != string::npos )
502                 coordinateSystem="CYLINDRICAL";
503
504             if(fileCOOR.rfind('/') == string::npos)
505                 // no directory was specified -> we add dirName, which may be empty
506                 coorFileName=dirName+fileCOOR;
507             else
508                 coorFileName=fileCOOR;
509         }
510
511
512         if (processLoca) 
513         {
514             // read group specification
515
516
517             // replace non digit caracters with blanks
518             string::iterator last_non_blank=buf_ligne.end();
519             for (string::iterator it=buf_ligne.begin(); it!=buf_ligne.end(); ++it)
520                 if ( !isdigit(*it) )
521                     *it=' ';
522                 else
523                     last_non_blank=it;
524
525             if (last_non_blank != buf_ligne.end() ) // if the line is not blank
526             {
527                 buf_ligne=string(buf_ligne.begin(),++last_non_blank); // suppress trailing blanks
528
529                 istringstream buf(buf_ligne.c_str());
530                 int i1;
531                 buf >> i1; // we know the line is not blank
532                 do
533                 {
534                     currentGroup.groupes.push_back(i1);
535                     buf >> i1;
536                 }
537                 while ( buf );
538
539             }
540         }
541         
542     }
543     if ( !currentGroup.groupes.empty() ) // if necessary, add the last group to medi.groupes
544         medi.groupes.push_back(currentGroup);
545
546     readPorflowCoordinateFile(coorFileName,medi,space_dimension);
547     readPorflowConnectivityFile(hybride,connFileName,medi,p_ma_table,space_dimension);
548
549
550     // Group processing :
551     //   In the scan loop, we have store in medi.groupes.groupes either :
552     //     - paired list of element and surface number (keyword PAIR)
553     //     - an explicit list of element numbers (keyword LIST)
554     //   What we stored (pairs or list) is remembered through vector isGroupAList.
555     //   For both cases, we must convert these numbers to iterators to cells inside the set medi.maillage
556     //     - in the LIST case, these cells already exist.
557     //     - in the PAIR case, we have to create the corresponding 2D/1D faces
558     // scan groups
559     //for( std::vector<_groupe>::iterator i=medi.groupes.begin(); i!=medi.groupes.end(); ++i)
560     for( int i=0; i!=medi.groupes.size(); ++i)
561     {
562         if ( isGroupAList[i] ) 
563         {
564             // medi.groupes[i].groupes is a vector of element numbers; it points to it
565             medi.groupes[i].mailles.resize( medi.groupes[i].groupes.size() );
566             std::vector<int>::const_iterator it=medi.groupes[i].groupes.begin();
567             for(int j = 0 ; it!=medi.groupes[i].groupes.end(); ++it, ++j)
568             {
569                 // insert the iterator to the corresponding cell we stored in p_ma_table
570                 medi.groupes[i].mailles[j] = p_ma_table[*it];
571             }
572             
573         }
574         else
575         {
576             int nelem=0;
577             int nface=0;
578             int ngeom=0;
579             int ielem=0;
580             std::set<_maille>::iterator p_ma;
581             _maille maille2D;
582             
583             // medi.groupes[i].groupes is a vector of paired element and surface numbers
584             // *it points to the element number,  *(it+1) points to the surface number
585             std::vector<int>::const_iterator it=medi.groupes[i].groupes.begin();
586             medi.groupes[i].mailles.resize( medi.groupes[i].groupes.size() / 2 );
587             for(  ; it!=medi.groupes[i].groupes.end(); ++it)
588             {
589                 nelem=*it;
590                 nface=*(++it);
591                 p_ma=p_ma_table[nelem]; // points to the cell
592                 ngeom=geomMEDtoPorflow(p_ma->geometricType);
593
594                 // create the face corresponding to nface
595                 int l=0;
596                 while( l<nb_nodes2_max && connectivityPORFLOW[ngeom][nface-1][l] )
597                 {
598                     maille2D.sommets.push_back(p_ma->sommets[ numPORFLOWtoMED[ngeom][ connectivityPORFLOW[ngeom][nface-1][l++]-1 ]-1 ]);
599                 }
600
601                 // the corresponding 2D MED geometric type depends upon the number of nodes
602                 maille2D.sommets.resize(l);
603                 maille2D.geometricType = get2DMedGeomType(l);
604                 p_ma = medi.maillage.insert(maille2D).first; // we insert the face in our mesh
605                 medi.groupes[i].mailles[ielem++]=p_ma; // and insert an iterator on it in our group
606                 maille2D.sommets.clear();
607             }
608
609         }
610         medi.groupes[i].groupes.clear(); // we don't need element numbers anymore
611         
612     }
613
614     p_ma_table.clear(); // we don't need it anymore
615     MESSAGE(LOC << "PORFLOW_MESH_RDONLY_DRIVER::read : RESULTATS STRUCTURE INTERMEDIAIRES : ");
616     MESSAGE(LOC <<  medi );
617             // TRANSFORMATION EN STRUCTURES MED
618     if ( ! _ptrMesh->isEmpty() )
619     {
620         throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Mesh object not empty : can't fill it!"));
621     }
622     else if ( medi.maillage.size()==0 || medi.groupes.size()==0 || medi.points.size()==0)
623     {
624         throw MEDEXCEPTION(LOCALIZED(STRING(LOC) << " Error while reading file " << _fileName 
625                     << " The data read are not completed " ) ) ;
626     }
627     else
628     {
629         _ptrMesh->_name = _meshName;
630         _ptrMesh->_spaceDimension = medi.points.begin()->second.coord.size();
631         _ptrMesh->_meshDimension = medi.maillage.rbegin()->dimension();
632         _ptrMesh->_numberOfNodes = medi.points.size();
633         _ptrMesh->_isAGrid = 0;
634         _ptrMesh->_coordinate = medi.getCoordinate();
635
636         //Construction des groupes
637         vector<GROUP *> groupCell, groupFace, groupEdge, groupNode;
638         medi.getGroups(groupCell, groupFace, groupEdge, groupNode, _ptrMesh);
639         _ptrMesh->_groupCell = groupCell;
640         _ptrMesh->_groupFace = groupFace;
641         _ptrMesh->_groupEdge = groupEdge;
642         _ptrMesh->_groupNode = groupNode;
643
644         // appele en dernier car cette fonction detruit le maillage intermediaire!
645         _ptrMesh->_connectivity = medi.getConnectivity(); 
646         MESSAGE(LOC << "PORFLOW_MESH_RDONLY_DRIVER::read : FIN ");
647
648         // calcul de la connectivite d-1 complete, avec renumerotation des groupes
649         // if (_ptrMesh->_spaceDimension==3)
650         //     _ptrMesh->_connectivity->updateGroup(_ptrMesh->_groupFace) ;
651         // else if (_ptrMesh->_spaceDimension==2)
652         //     _ptrMesh->_connectivity->updateGroup(_ptrMesh->_groupEdge) ;
653         
654         // Creation des familles ?artir des groupes
655         // NC : Cet appel pourra ?e diff鲩 quand la gestion de la coh鲥nce famille/groupes sera assur饊      _ptrMesh->createFamilies();
656     }
657
658
659     END_OF(LOC);
660 }
661
662 void PORFLOW_MESH_RDONLY_DRIVER::write( void ) const
663   throw (MEDEXCEPTION)
664 {
665   throw MEDEXCEPTION("PORFLOW_MESH_RDONLY_DRIVER::write : Can't write with a RDONLY driver !");
666 }
667
668
669 /*--------------------- WRONLY PART -------------------------------*/
670
671 PORFLOW_MESH_WRONLY_DRIVER::PORFLOW_MESH_WRONLY_DRIVER():PORFLOW_MESH_DRIVER()
672 {
673 }
674   
675 PORFLOW_MESH_WRONLY_DRIVER::PORFLOW_MESH_WRONLY_DRIVER(const string & fileName,
676                                                  MESH * ptrMesh):
677   PORFLOW_MESH_DRIVER(fileName,ptrMesh,MED_WRONLY)
678 {
679   MESSAGE("PORFLOW_MESH_WRONLY_DRIVER::PORFLOW_MESH_WRONLY_DRIVER(const string & fileName, MESH * ptrMesh) has been created");
680 }
681
682 PORFLOW_MESH_WRONLY_DRIVER::PORFLOW_MESH_WRONLY_DRIVER(const PORFLOW_MESH_WRONLY_DRIVER & driver): 
683   PORFLOW_MESH_DRIVER(driver)
684 {
685 }
686
687 PORFLOW_MESH_WRONLY_DRIVER::~PORFLOW_MESH_WRONLY_DRIVER()
688 {
689   //MESSAGE("PORFLOW_MESH_WRONLY_DRIVER::PORFLOW_MESH_WRONLY_DRIVER(const string & fileName, MESH * ptrMesh) has been destroyed");
690 }
691
692 GENDRIVER * PORFLOW_MESH_WRONLY_DRIVER::copy(void) const
693 {
694   return new PORFLOW_MESH_WRONLY_DRIVER(*this);
695 }
696
697 void PORFLOW_MESH_WRONLY_DRIVER::read (void)
698   throw (MEDEXCEPTION)
699 {
700   throw MEDEXCEPTION("PORFLOW_MESH_WRONLY_DRIVER::read : Can't read with a WRONLY driver !");
701 }
702
703 void PORFLOW_MESH_WRONLY_DRIVER::write(void) const
704   throw (MEDEXCEPTION)
705
706   const char * LOC = "void PORFLOW_MESH_WRONLY_DRIVER::write(void) const : ";
707   BEGIN_OF(LOC);
708
709   throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<< "Write Driver isn\'t implemented"));
710
711   END_OF(LOC);
712
713
714
715
716 /*--------------------- RDWR PART -------------------------------*/
717
718 PORFLOW_MESH_RDWR_DRIVER::PORFLOW_MESH_RDWR_DRIVER():PORFLOW_MESH_DRIVER()
719 {
720 }
721
722 PORFLOW_MESH_RDWR_DRIVER::PORFLOW_MESH_RDWR_DRIVER(const string & fileName,
723                                            MESH * ptrMesh):
724   PORFLOW_MESH_DRIVER(fileName,ptrMesh,MED_RDWR)
725 {
726   MESSAGE("PORFLOW_MESH_RDWR_DRIVER::PORFLOW_MESH_RDWR_DRIVER(const string & fileName, MESH * ptrMesh) has been created");
727 }
728
729 PORFLOW_MESH_RDWR_DRIVER::PORFLOW_MESH_RDWR_DRIVER(const PORFLOW_MESH_RDWR_DRIVER & driver): 
730   PORFLOW_MESH_RDONLY_DRIVER::PORFLOW_MESH_DRIVER(driver)
731 {
732 }
733
734 PORFLOW_MESH_RDWR_DRIVER::~PORFLOW_MESH_RDWR_DRIVER() {
735   //MESSAGE("PORFLOW_MESH_RDWR_DRIVER::PORFLOW_MESH_RDWR_DRIVER(const string & fileName, MESH * ptrMesh) has been destroyed");
736
737   
738 GENDRIVER * PORFLOW_MESH_RDWR_DRIVER::copy(void) const
739 {
740   return new PORFLOW_MESH_RDWR_DRIVER(*this);
741 }
742
743 void PORFLOW_MESH_RDWR_DRIVER::write(void) const
744   throw (MEDEXCEPTION)
745 {
746   PORFLOW_MESH_WRONLY_DRIVER::write();
747 }
748 void PORFLOW_MESH_RDWR_DRIVER::read (void)
749   throw (MEDEXCEPTION)
750 {
751   PORFLOW_MESH_RDONLY_DRIVER::read();
752 }