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