Salome HOME
Building a version which will be tagged PreV2_0_0 working with KERNEL V1_4_0.
[modules/med.git] / src / MEDMEM / MEDMEM_PorflowMeshDriver.cxx
1 using namespace std;
2
3 #include "MEDMEM_PorflowMeshDriver.hxx"
4 #include "MEDMEM_DriversDef.hxx"
5 #include "MEDMEM_DriverTools.hxx"
6
7 #include "MEDMEM_Family.hxx"
8 #include "MEDMEM_Group.hxx"
9 #include "MEDMEM_Coordinate.hxx"
10 #include "MEDMEM_Connectivity.hxx"
11 #include "MEDMEM_Mesh.hxx"
12 #include "MEDMEM_CellModel.hxx"
13 #include "MEDMEM_define.hxx"
14 #include <string.h>
15 #include <ctype.h>
16 #include <iostream>
17 #include <sstream>
18 #include <iomanip>
19
20 using namespace MED_EN;
21 using namespace MEDMEM;
22
23 // geometric types conversion from PORFLOW -> MED
24 const size_t PORFLOW_MESH_DRIVER::nb_geometrie_porflow;
25 const medGeometryElement PORFLOW_MESH_DRIVER::geomPORFLOWtoMED[nb_geometrie_porflow] =
26   {   /*  1  */ MED_TRIA3   ,/*  2  */ MED_QUAD4  ,/*  3  */ MED_TETRA4  ,/*  4  */ MED_PYRA5  ,
27       /*  5  */ MED_PENTA6  ,/*  6  */ MED_HEXA8   };
28 // indirection table from PORFLOW order to MED one for nodes numerotation in all PORFLOW geometries
29 const size_t PORFLOW_MESH_DRIVER::nb_nodes_max;
30
31 // conversion from porflow connectivity to MED connectivity
32 const int PORFLOW_MESH_DRIVER::numPORFLOWtoMED[nb_geometrie_porflow] [nb_nodes_max] = {
33       /*  TRI3   */ { /*1*/ 1, /*2*/ 3, /*3*/ 2 },
34       /*  QUA4   */ { /*1*/ 1, /*2*/ 4, /*3*/ 3, /*4*/ 2 },
35       /*  TETRA4 */ { /*1*/ 1, /*2*/ 4, /*3*/ 3, /*4*/ 2 },
36       /*  PYRA5  */ { /*1*/ 1, /*2*/ 4, /*3*/ 3, /*4*/ 2, /*5*/ 5 },
37       /*  PENTA6 */ { /*1*/ 1, /*2*/ 3, /*3*/ 2, /*4*/ 4, /*5*/ 6, /*6*/ 5 },
38       /*  HEXA8  */ { /*1*/ 1, /*2*/ 4, /*3*/ 3, /*4*/ 2, /*5*/ 5, /*6*/ 8, /*7*/ 7, /*8*/ 6 } };
39
40 // Porflox nodal connectivity of faces - documented in Porflow user's manual
41 const size_t PORFLOW_MESH_DRIVER::nb_faces_max;
42 const size_t PORFLOW_MESH_DRIVER::nb_nodes2_max;
43 const int PORFLOW_MESH_DRIVER::connectivityPORFLOW[nb_geometrie_porflow][nb_faces_max][nb_nodes2_max]={
44   //{/* 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} },
45   //{/* 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} },
46     {/* 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} },
47     {/* 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} },
48     {/* 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} },
49     {/* 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} },
50     {/* 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} },
51     {/* 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} },
52 };
53
54 // helper function
55 inline static bool isKeyWord(const string & line, const char * key);
56 inline static void locateFileName(const string& line, string::size_type& pos1, string::size_type& pos2);
57 inline static string getPorflowFileName(const string& line, const char * context);
58 inline static medGeometryElement get2DMedGeomType(int nbSommets);
59
60
61 // Every memory allocation made in the MedDriver members function are desallocated in the Mesh destructor 
62
63 PORFLOW_MESH_DRIVER::PORFLOW_MESH_DRIVER():
64   GENDRIVER(),
65   _ptrMesh(( MESH *)MED_NULL),
66   // A VOIR _medIdt(MED_INVALID),
67   _meshName("")
68 {
69 }
70
71 PORFLOW_MESH_DRIVER::PORFLOW_MESH_DRIVER(const string & fileName,
72                                    MESH * ptrMesh,
73                                    MED_EN::med_mode_acces accessMode): 
74   GENDRIVER(fileName,accessMode),
75   _ptrMesh(ptrMesh)
76 {
77     // mesh name construction from fileName
78     const string ext=".inp"; // expected extension
79     string::size_type pos=fileName.find(ext,0);
80     string::size_type pos1=fileName.rfind('/');
81     _meshName = string(fileName,pos1+1,pos-pos1-1); //get rid of directory & extension
82     SCRUTE(_meshName);
83 }
84   
85 PORFLOW_MESH_DRIVER::PORFLOW_MESH_DRIVER(const PORFLOW_MESH_DRIVER & driver): 
86   GENDRIVER(driver),
87   _ptrMesh(driver._ptrMesh),
88   // A VOIR _medIdt(MED_INVALID), 
89   _meshName(driver._meshName)
90 {
91 }
92
93 PORFLOW_MESH_DRIVER::~PORFLOW_MESH_DRIVER()
94 {
95 }
96
97 void PORFLOW_MESH_DRIVER::open()
98   throw (MEDEXCEPTION)
99 {
100     const char * LOC = "PORFLOW_MESH_DRIVER::open()" ;
101     BEGIN_OF(LOC);
102     _porflow.open(_fileName.c_str(), ios::in);
103     if(_porflow)
104         _status = MED_OPENED;
105     else
106     {
107         _status = MED_CLOSED;
108         throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<" Could not open file "<<_fileName<<" in mode ios::in"));
109     }
110     END_OF(LOC);
111 }
112   
113 void PORFLOW_MESH_DRIVER::close()
114   throw (MEDEXCEPTION)
115 {
116     const char * LOC = "PORFLOW_MESH_DRIVER::close() " ;
117     BEGIN_OF(LOC);
118     if ( _status == MED_OPENED) 
119     {
120         _porflow.close();
121         _status = MED_CLOSED;
122     }
123     END_OF(LOC);
124 }
125
126 void    PORFLOW_MESH_DRIVER::setMeshName(const string & meshName) { _meshName = meshName; };
127 string  PORFLOW_MESH_DRIVER::getMeshName() const { return _meshName; };
128
129
130 //---------------------------------- RDONLY PART -------------------------------------------------------------
131
132 PORFLOW_MESH_RDONLY_DRIVER::PORFLOW_MESH_RDONLY_DRIVER(): PORFLOW_MESH_DRIVER()
133 {
134 }
135   
136 PORFLOW_MESH_RDONLY_DRIVER::PORFLOW_MESH_RDONLY_DRIVER(const string & fileName,
137                                                  MESH * ptrMesh):
138   PORFLOW_MESH_DRIVER(fileName,ptrMesh,MED_RDONLY)
139
140   MESSAGE("PORFLOW_MESH_RDONLY_DRIVER::PORFLOW_MESH_RDONLY_DRIVER(const string & fileName, MESH * ptrMesh) has been created");
141 }
142   
143 PORFLOW_MESH_RDONLY_DRIVER::PORFLOW_MESH_RDONLY_DRIVER(const PORFLOW_MESH_RDONLY_DRIVER & driver): 
144   PORFLOW_MESH_DRIVER(driver)
145 {
146 }
147
148 PORFLOW_MESH_RDONLY_DRIVER::~PORFLOW_MESH_RDONLY_DRIVER()
149 {
150   //MESSAGE("PORFLOW_MESH_RDONLY_DRIVER::~PORFLOW_MESH_RDONLY_DRIVER() has been destroyed");
151 }
152   
153 GENDRIVER * PORFLOW_MESH_RDONLY_DRIVER::copy(void) const
154 {
155   return new PORFLOW_MESH_RDONLY_DRIVER(*this);
156 }
157
158 // helper function to check if line starts with key
159 inline static bool isKeyWord(const string & line, const char * key)
160 {
161     const int SIZE_KEY=4;
162     const char * pt=line.c_str();
163     while( isspace(*pt) ) // get rid of leading blanks
164         ++pt;
165     return !strncmp(pt,key,SIZE_KEY);
166 }
167
168 inline static void locateFileName(const string& line, string::size_type& pos1, string::size_type& pos2)
169 {
170     pos1 = line.find('"',0);
171     if ( pos1 != string::npos ) // if we found "
172         pos2=line.find('"',pos1+1); // search a second "
173     else // we didn't succeed with double quotes, so we try single quotes
174     {
175         pos1 = line.find('\'',0);
176         if ( pos1 != string::npos ) // if we found '
177             pos2=line.find('\'',pos1+1); // search a second '
178     }
179 }
180
181
182 // helper fonction : inversion of PORFLOW_MESH_DRIVER::geomPORFLOWtoMED
183 // return the Porflow geometric type, -1 if not found
184 inline int PORFLOW_MESH_DRIVER::geomMEDtoPorflow(medGeometryElement medGeo)
185 {
186     for (int g=0; g!=nb_geometrie_porflow; ++g)
187         if( medGeo == geomPORFLOWtoMED[g] )
188             return g;
189     return -1;
190 }
191
192
193 // Correspondance between the number of nodes and the Med face geometric type
194 inline static medGeometryElement get2DMedGeomType(int nbSommets)
195 {
196     switch (nbSommets)
197     {
198         case 2:
199             return MED_SEG2;
200             break;
201         case 3:
202             return MED_TRIA3;
203             break;
204         case 4:
205             return MED_QUAD4;
206             break;
207     } 
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                 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 détecté");
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             std::vector<int>::const_iterator it=medi.groupes[i].groupes.begin();
566             for(  ; it!=medi.groupes[i].groupes.end(); ++it)
567             {
568                 // insert the iterator to the corresponding cell we stored in p_ma_table
569                 medi.groupes[i].mailles.insert( p_ma_table[*it] );
570             }
571             
572         }
573         else
574         {
575             int nelem=0;
576             int nface=0;
577             int ngeom=0;
578             std::set<_maille>::iterator p_ma;
579             _maille maille2D;
580             
581             // medi.groupes[i].groupes is a vector of paired element and surface numbers
582             // *it points to the element number,  *(it+1) points to the surface number
583             std::vector<int>::const_iterator it=medi.groupes[i].groupes.begin();
584             for(  ; it!=medi.groupes[i].groupes.end(); ++it)
585             {
586                 nelem=*it;
587                 nface=*(++it);
588                 p_ma=p_ma_table[nelem]; // points to the cell
589                 ngeom=geomMEDtoPorflow(p_ma->geometricType);
590
591                 // create the face corresponding to nface
592                 int l=0;
593                 while( l<nb_nodes2_max && connectivityPORFLOW[ngeom][nface-1][l] )
594                 {
595                     maille2D.sommets.push_back(p_ma->sommets[ numPORFLOWtoMED[ngeom][ connectivityPORFLOW[ngeom][nface-1][l++]-1 ]-1 ]);
596                 }
597
598                 // the corresponding 2D MED geometric type depends upon the number of nodes
599                 maille2D.sommets.resize(l);
600                 maille2D.geometricType = get2DMedGeomType(l);
601                 p_ma = medi.maillage.insert(maille2D).first; // we insert the face in our mesh
602                 medi.groupes[i].mailles.insert(p_ma); // and insert an iterator on it in our group
603                 maille2D.sommets.clear();
604             }
605
606         }
607         // medi.groupes[i].groupes.clear(); // we don't need element numbers anymore
608         
609     }
610
611     p_ma_table.clear(); // we don't need it anymore
612     MESSAGE(LOC << "GIBI_MESH_RDONLY_DRIVER::read : RESULTATS STRUCTURE INTERMEDIAIRES : ");
613     MESSAGE(LOC <<  medi );
614             // TRANSFORMATION EN STRUCTURES MED
615     if ( ! _ptrMesh->isEmpty() )
616     {
617         throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Mesh object not empty : can't fill it!"));
618     }
619     else if ( medi.maillage.size()==0 || medi.groupes.size()==0 || medi.points.size()==0)
620     {
621         throw MEDEXCEPTION(LOCALIZED(STRING(LOC) << " Error while reading file " << _fileName 
622                     << " The data read are not completed " ) ) ;
623     }
624     else
625     {
626         _ptrMesh->_name = _meshName;
627         _ptrMesh->_spaceDimension = medi.points.begin()->second.coord.size();
628         _ptrMesh->_meshDimension = medi.maillage.rbegin()->dimension();
629         _ptrMesh->_numberOfNodes = medi.points.size();
630         _ptrMesh->_isAGrid = 0;
631         _ptrMesh->_coordinate = medi.getCoordinate();
632
633         //Construction des groupes
634         vector<GROUP *> groupCell, groupFace, groupEdge, groupNode;
635         medi.getGroups(groupCell, groupFace, groupEdge, groupNode, _ptrMesh);
636         _ptrMesh->_groupCell = groupCell;
637         _ptrMesh->_groupFace = groupFace;
638         _ptrMesh->_groupEdge = groupEdge;
639         _ptrMesh->_groupNode = groupNode;
640
641         // appele en dernier car cette fonction detruit le maillage intermediaire!
642         _ptrMesh->_connectivity = medi.getConnectivity(); 
643         MESSAGE(LOC << "GIBI_MESH_RDONLY_DRIVER::read : FIN ");
644
645         // calcul de la connectivite d-1 complete, avec renumerotation des groupes
646         // if (_ptrMesh->_spaceDimension==3)
647         //     _ptrMesh->_connectivity->updateGroup(_ptrMesh->_groupFace) ;
648         // else if (_ptrMesh->_spaceDimension==2)
649         //     _ptrMesh->_connectivity->updateGroup(_ptrMesh->_groupEdge) ;
650         
651         // Creation des familles à partir des groupes
652         // NC : Cet appel pourra être différé quand la gestion de la cohérence famille/groupes sera assurée
653         _ptrMesh->createFamilies();
654     }
655
656
657     END_OF(LOC);
658 }
659
660 void PORFLOW_MESH_RDONLY_DRIVER::write( void ) const
661   throw (MEDEXCEPTION)
662 {
663   throw MEDEXCEPTION("PORFLOW_MESH_RDONLY_DRIVER::write : Can't write with a RDONLY driver !");
664 }
665
666
667 /*--------------------- WRONLY PART -------------------------------*/
668
669 PORFLOW_MESH_WRONLY_DRIVER::PORFLOW_MESH_WRONLY_DRIVER():PORFLOW_MESH_DRIVER()
670 {
671 }
672   
673 PORFLOW_MESH_WRONLY_DRIVER::PORFLOW_MESH_WRONLY_DRIVER(const string & fileName,
674                                                  MESH * ptrMesh):
675   PORFLOW_MESH_DRIVER(fileName,ptrMesh,MED_WRONLY)
676 {
677   MESSAGE("PORFLOW_MESH_WRONLY_DRIVER::PORFLOW_MESH_WRONLY_DRIVER(const string & fileName, MESH * ptrMesh) has been created");
678 }
679
680 PORFLOW_MESH_WRONLY_DRIVER::PORFLOW_MESH_WRONLY_DRIVER(const PORFLOW_MESH_WRONLY_DRIVER & driver): 
681   PORFLOW_MESH_DRIVER(driver)
682 {
683 }
684
685 PORFLOW_MESH_WRONLY_DRIVER::~PORFLOW_MESH_WRONLY_DRIVER()
686 {
687   //MESSAGE("PORFLOW_MESH_WRONLY_DRIVER::PORFLOW_MESH_WRONLY_DRIVER(const string & fileName, MESH * ptrMesh) has been destroyed");
688 }
689
690 GENDRIVER * PORFLOW_MESH_WRONLY_DRIVER::copy(void) const
691 {
692   return new PORFLOW_MESH_WRONLY_DRIVER(*this);
693 }
694
695 void PORFLOW_MESH_WRONLY_DRIVER::read (void)
696   throw (MEDEXCEPTION)
697 {
698   throw MEDEXCEPTION("PORFLOW_MESH_WRONLY_DRIVER::read : Can't read with a WRONLY driver !");
699 }
700
701 void PORFLOW_MESH_WRONLY_DRIVER::write(void) const
702   throw (MEDEXCEPTION)
703
704   const char * LOC = "void PORFLOW_MESH_WRONLY_DRIVER::write(void) const : ";
705   BEGIN_OF(LOC);
706
707   throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<< "Write Driver isn\'t implemented"));
708
709   END_OF(LOC);
710
711
712
713
714 /*--------------------- RDWR PART -------------------------------*/
715
716 PORFLOW_MESH_RDWR_DRIVER::PORFLOW_MESH_RDWR_DRIVER():PORFLOW_MESH_DRIVER()
717 {
718 }
719
720 PORFLOW_MESH_RDWR_DRIVER::PORFLOW_MESH_RDWR_DRIVER(const string & fileName,
721                                            MESH * ptrMesh):
722   PORFLOW_MESH_DRIVER(fileName,ptrMesh,MED_RDWR)
723 {
724   MESSAGE("PORFLOW_MESH_RDWR_DRIVER::PORFLOW_MESH_RDWR_DRIVER(const string & fileName, MESH * ptrMesh) has been created");
725 }
726
727 PORFLOW_MESH_RDWR_DRIVER::PORFLOW_MESH_RDWR_DRIVER(const PORFLOW_MESH_RDWR_DRIVER & driver): 
728   PORFLOW_MESH_RDONLY_DRIVER::PORFLOW_MESH_DRIVER(driver)
729 {
730 }
731
732 PORFLOW_MESH_RDWR_DRIVER::~PORFLOW_MESH_RDWR_DRIVER() {
733   //MESSAGE("PORFLOW_MESH_RDWR_DRIVER::PORFLOW_MESH_RDWR_DRIVER(const string & fileName, MESH * ptrMesh) has been destroyed");
734
735   
736 GENDRIVER * PORFLOW_MESH_RDWR_DRIVER::copy(void) const
737 {
738   return new PORFLOW_MESH_RDWR_DRIVER(*this);
739 }
740
741 void PORFLOW_MESH_RDWR_DRIVER::write(void) const
742   throw (MEDEXCEPTION)
743 {
744   PORFLOW_MESH_WRONLY_DRIVER::write();
745 }
746 void PORFLOW_MESH_RDWR_DRIVER::read (void)
747   throw (MEDEXCEPTION)
748 {
749   PORFLOW_MESH_RDONLY_DRIVER::read();
750 }