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