Salome HOME
update due to bugs PAL8113 and another I do not remember the number ;) .
[modules/med.git] / src / MEDMEM / MEDMEM_Mesh.cxx
index 94e9a0533bd47649ac9ef79ba699e0625670d2bc..9a3a4485c6ee4c5cd5e617ee6b9ec5be1805f423 100644 (file)
@@ -1,30 +1,3 @@
-//  MED MEDMEM : MED files in memory
-//
-//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
-//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
-// 
-//  This library is free software; you can redistribute it and/or 
-//  modify it under the terms of the GNU Lesser General Public 
-//  License as published by the Free Software Foundation; either 
-//  version 2.1 of the License. 
-// 
-//  This library is distributed in the hope that it will be useful, 
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of 
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
-//  Lesser General Public License for more details. 
-// 
-//  You should have received a copy of the GNU Lesser General Public 
-//  License along with this library; if not, write to the Free Software 
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
-// 
-//  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
-//
-//
-//
-//  File   : MEDMEM_Mesh.cxx
-//  Module : MED
-
-using namespace std;
 /*
  File Mesh.cxx
  $Header$
@@ -34,6 +7,7 @@ using namespace std;
 
 #include <list>
 #include <map>
+#include <sstream>
 
 #include "MEDMEM_DriversDef.hxx"
 #include "MEDMEM_Field.hxx"
@@ -45,48 +19,51 @@ using namespace std;
 #include "MEDMEM_Coordinate.hxx"
 #include "MEDMEM_Connectivity.hxx"
 #include "MEDMEM_CellModel.hxx"
-#include "MEDMEM_Grid.hxx"
+
+#include "MEDMEM_DriverFactory.hxx"
+
+using namespace std;
+using namespace MEDMEM;
+using namespace MED_EN;
+
+//#include "MEDMEM_Grid.hxx" this inclision should have never be here !!!
 
 //update Families with content list
 //int family_count(int family_number, int count, int * entities_number, int * entities_list) ;
 
 // ------- Drivers Management Part
 
-// MESH::INSTANCE_DE<MED_MESH_RDONLY_DRIVER> MESH::inst_med_rdonly ;
-//const MESH::INSTANCE * const MESH::instances[] = { &MESH::inst_med_rdonly , &MESH::inst_med_rdwr } ;
-
-// Add a similar line for your personnal driver (step 3)
-MESH::INSTANCE_DE<MED_MESH_RDWR_DRIVER>   MESH::inst_med   ;
-MESH::INSTANCE_DE<GIBI_MESH_RDWR_DRIVER>  MESH::inst_gibi ;
-// Add your own driver in the driver list       (step 4)
-// Note the list must be coherent with the driver type list defined in MEDMEM_DRIVER.hxx. 
-const MESH::INSTANCE * const MESH::instances[] =   {  &MESH::inst_med, &MESH::inst_gibi } ;
-
-/*! Add a MESH driver of type (MED_DRIVER, ....) associated with file <fileName>. The meshname used in the file
-    is  <driverName>. addDriver returns an int handler. */
+/*! Add a %MESH driver of type %driverTypes (MED_DRIVER, ....) associated with file fileName. The meshname used in the file
+    is  driverName. addDriver returns an integer handler. */
 int MESH::addDriver(driverTypes driverType, 
-                    const string & fileName/*="Default File Name.med"*/,const string & driverName/*="Default Mesh Name"*/) {
+                    const string & fileName/*="Default File Name.med"*/,
+                   const string & driverName/*="Default Mesh Name"*/,
+                   med_mode_acces access) {
 
-  const char * LOC = "MESH::addDriver(driverTypes driverType, const string & fileName=\"Default File Name.med\",const string & driverName=\"Default Mesh Name\") : ";
+  const char * LOC = "MESH::addDriver(driverTypes driverType, const string & fileName=\"Default File Name.med\",const string & driverName=\"Default Mesh Name\",MED_EN::med_mode_acces access) : ";
   
   GENDRIVER * driver;
-  int current;
 
   BEGIN_OF(LOC);
   
-  driver = instances[driverType]->run(fileName, this) ;
+  SCRUTE(driverType);
+
+  driver = DRIVERFACTORY::buildDriverForMesh(driverType,fileName,this,
+                                            driverName,access) ;
+
   _drivers.push_back(driver);
-  current = _drivers.size()-1;
+
+  int current = _drivers.size()-1;
   
   _drivers[current]->setMeshName(driverName);  
-  return current;
 
   END_OF(LOC);
 
+  return current;
 }
 
 /*! Add an existing MESH driver. */
-int  MESH::addDriver(MED_MESH_DRIVER & driver) {
+int  MESH::addDriver(GENDRIVER & driver) {
   const char * LOC = "MESH::addDriver(GENDRIVER &) : ";
   BEGIN_OF(LOC);
 
@@ -129,30 +106,24 @@ void MESH::init() {
 
   BEGIN_OF(LOC);
 
-  string        _name = "NOT DEFINED"; // A POSITIONNER EN FCT DES IOS ?
+  _name = "NOT DEFINED"; // A POSITIONNER EN FCT DES IOS ?
 
-  COORDINATE   * _coordinate   = (COORDINATE   *) NULL;
-  CONNECTIVITY * _connectivity = (CONNECTIVITY *) NULL;
+  _coordinate   = (COORDINATE   *) NULL;
+  _connectivity = (CONNECTIVITY *) NULL;
 
   _spaceDimension        =          MED_INVALID; // 0 ?!?
   _meshDimension         =          MED_INVALID;
   _numberOfNodes         =          MED_INVALID;
-  
-  _numberOfNodesFamilies =          0; // MED_INVALID ?!?
-  _numberOfCellsFamilies =          0;
-  _numberOfFacesFamilies =          0;
-  _numberOfEdgesFamilies =          0;
-
-  _numberOfNodesGroups   =          0;  // MED_INVALID ?!?
-  _numberOfCellsGroups   =          0; 
-  _numberOfFacesGroups   =          0; 
-  _numberOfEdgesGroups   =          0; 
 
   _isAGrid = false;
+  _arePresentOptionnalNodesNumbers = 0;
+
+  END_OF(LOC);
 };
 
 /*! Create an empty MESH. */
-MESH::MESH():_coordinate(NULL),_connectivity(NULL) {
+MESH::MESH():_coordinate(NULL),_connectivity(NULL), _isAGrid(false) {
   init();
 };
 
@@ -175,65 +146,57 @@ MESH::MESH(MESH &m)
   _meshDimension = m._meshDimension;
   _numberOfNodes = m._numberOfNodes;
 
-  _numberOfNodesFamilies = m._numberOfNodesFamilies;
   _familyNode = m._familyNode;
-  for (int i=0; i<m._numberOfNodesFamilies; i++)
+  for (int i=0; i<m._familyNode.size(); i++)
     {
       _familyNode[i] = new FAMILY(* m._familyNode[i]);
       _familyNode[i]->setMesh(this);
     }
 
-  _numberOfCellsFamilies = m._numberOfCellsFamilies;
   _familyCell = m._familyCell;
-  for (int i=0; i<m._numberOfCellsFamilies; i++)
+  for (int i=0; i<m._familyCell.size(); i++)
     {
       _familyCell[i] = new FAMILY(* m._familyCell[i]);
       _familyCell[i]->setMesh(this);
     }
 
-  _numberOfFacesFamilies = m._numberOfFacesFamilies;
   _familyFace = m._familyFace;
-  for (int i=0; i<m._numberOfFacesFamilies; i++)
+  for (int i=0; i<m._familyFace.size(); i++)
     {
       _familyFace[i] = new FAMILY(* m._familyFace[i]);
       _familyFace[i]->setMesh(this);
     }
 
-  _numberOfEdgesFamilies = m._numberOfEdgesFamilies;
   _familyEdge = m._familyEdge;
-  for (int i=0; i<m._numberOfEdgesFamilies; i++)
+  for (int i=0; i<m._familyEdge.size(); i++)
     {
       _familyEdge[i] = new FAMILY(* m._familyEdge[i]);
       _familyEdge[i]->setMesh(this);
     }
 
-  _numberOfNodesGroups = m._numberOfNodesGroups;
   _groupNode = m._groupNode;
-  for (int i=0; i<m._numberOfNodesGroups; i++)
+  for (int i=0; i<m._groupNode.size(); i++)
     {
       _groupNode[i] = new GROUP(* m._groupNode[i]);
       _groupNode[i]->setMesh(this);
     }
 
-  _numberOfCellsGroups = m._numberOfCellsGroups;
   _groupCell = m._groupCell;
-  for (int i=0; i<m._numberOfCellsGroups; i++)
+  for (int i=0; i<m._groupCell.size(); i++)
     {
       _groupCell[i] = new GROUP(* m._groupCell[i]);
       _groupCell[i]->setMesh(this);
     }
 
-  _numberOfFacesGroups = m._numberOfFacesGroups;
   _groupFace = m._groupFace;
-  for (int i=0; i<m._numberOfFacesGroups; i++)
+  for (int i=0; i<m._groupFace.size(); i++)
     {
       _groupFace[i] = new GROUP(* m._groupFace[i]);
       _groupFace[i]->setMesh(this);
     }
 
-  _numberOfEdgesGroups = m._numberOfEdgesGroups;
   _groupEdge = m._groupEdge;
-  for (int i=0; i<m._numberOfEdgesGroups; i++)
+  for (int i=0; i<m._groupEdge.size(); i++)
     {
       _groupEdge[i] = new GROUP(* m._groupEdge[i]);
       _groupEdge[i]->setMesh(this);
@@ -250,40 +213,32 @@ MESH::~MESH() {
   int size ;
   size = _familyNode.size() ;
   for (int i=0;i<size;i++)
-    ;// mpv such destructors call is problemmatic for ALLIANCES algorithms
-    //delete _familyNode[i] ;
+    delete _familyNode[i] ;
   size = _familyCell.size() ;
   for (int i=0;i<size;i++)
-    ;// mpv such destructors call is problemmatic for ALLIANCES algorithms
-    //delete _familyCell[i] ;
+    delete _familyCell[i] ;
   size = _familyFace.size() ;
   for (int i=0;i<size;i++)
-    ;// mpv such destructors call is problemmatic for ALLIANCES algorithms
-    //delete _familyFace[i] ;
+    delete _familyFace[i] ;
   size = _familyEdge.size() ;
   for (int i=0;i<size;i++)
-    ;// mpv such destructors call is problemmatic for ALLIANCES algorithms
-    //delete _familyEdge[i] ;
+    delete _familyEdge[i] ;
   size = _groupNode.size() ;
   for (int i=0;i<size;i++)
-    ;// mpv such destructors call is problemmatic for ALLIANCES algorithms
-    //delete _groupNode[i] ;
+    delete _groupNode[i] ;
   size = _groupCell.size() ;
   for (int i=0;i<size;i++)
-    ;// mpv such destructors call is problemmatic for ALLIANCES algorithms
-    //delete _groupCell[i] ;
+    delete _groupCell[i] ;
   size = _groupFace.size() ;
   for (int i=0;i<size;i++)
-    ;// mpv such destructors call is problemmatic for ALLIANCES algorithms
-    //delete _groupFace[i] ;
+    delete _groupFace[i] ;
   size = _groupEdge.size() ;
   for (int i=0;i<size;i++)
-    ;// mpv such destructors call is problemmatic for ALLIANCES algorithms
-    //delete _groupEdge[i] ;
+    delete _groupEdge[i] ;
 
   MESSAGE("In this object MESH there is(are) " << _drivers.size() << " driver(s)");
 
-  for (int index=0; index < _drivers.size(); index++ )
+  for (unsigned int index=0; index < _drivers.size(); index++ )
     {
       SCRUTE(_drivers[index]);
       if ( _drivers[index] != NULL) delete _drivers[index];
@@ -293,7 +248,10 @@ MESH::~MESH() {
 
 MESH & MESH::operator=(const MESH &m)
 {
+  const char * LOC = "MESH & MESH::operator=(const MESH &m) : ";
+  BEGIN_OF(LOC);
 
+  MESSAGE(LOC <<"Not yet implemented, operating on the object " << m);
   //  A FAIRE.........
 
   // ATTENTION CET OPERATEUR DE RECOPIE EST DANGEREUX POUR LES
@@ -326,38 +284,30 @@ MESH & MESH::operator=(const MESH &m)
 //        reverse_nodal_connectivity = m.reverse_nodal_connectivity;
 //        reverse_nodal_connectivity_index = m.reverse_nodal_connectivity_index ;
 //      }
+  END_OF(LOC);
+
   return *this;
 }
 
-/*! Create a MESH object using a MESH driver of type (MED_DRIVER, ....) associated with file <fileName>. 
-  The meshname <driverName> must already exists in the file.*/
-MESH::MESH(driverTypes driverType, const string &  fileName/*=""*/, const string &  driverName/*=""*/) {
+/*! Create a %MESH object using a %MESH driver of type %driverTypes (MED_DRIVER, ....) associated with file fileName. 
+  The meshname driverName must already exists in the file.*/
+MESH::MESH(driverTypes driverType, const string &  fileName/*=""*/, const string &  driverName/*=""*/) throw (MEDEXCEPTION)
+{
   const char * LOC ="MESH::MESH(driverTypes driverType, const string &  fileName="", const string &  driverName="") : ";
-  
   int current;
   
   BEGIN_OF(LOC);
 
   init();
-
-  MED_MESH_RDONLY_DRIVER myDriver(fileName,this) ;
-  myDriver.setMeshName(driverName);
-  current = addDriver(myDriver);
-//   current = addDriver(driverType,fileName,driverName);
-//   switch(_drivers[current]->getAccessMode() ) {
-//   case MED_WRONLY : {
-//     MESSAGE("MESH::MESH(driverTypes driverType, .....) : driverType must not be a MED_WRONLY accessMode");
-//     rmDriver(current);
-//     break;}
-//   default : {
-//   }
-//   }
+  GENDRIVER *myDriver=DRIVERFACTORY::buildDriverForMesh(driverType,fileName,this,driverName,MED_LECT);
+  current = addDriver(*myDriver);
+  delete myDriver;
   _drivers[current]->open();   
   _drivers[current]->read();
   _drivers[current]->close();
 
-  if (_isAGrid)
-    ((GRID *) this)->fillMeshAfterRead();
+//   if (_isAGrid)
+//     ((GRID *) this)->fillMeshAfterRead();
 
   END_OF(LOC);
 };
@@ -371,7 +321,7 @@ MESH::MESH(driverTypes driverType, const string &  fileName/*=""*/, const string
 //    return N;
 //  }
 
-ostream & operator<<(ostream &os, MESH &myMesh)
+ostream & MEDMEM::operator<<(ostream &os, const MESH &myMesh)
 {
   int spacedimension = myMesh.getSpaceDimension();
   int meshdimension  = myMesh.getMeshDimension();
@@ -404,49 +354,8 @@ ostream & operator<<(ostream &os, MESH &myMesh)
       os << endl;
     }
 
-  const CONNECTIVITY * myConnectivity = myMesh.getConnectivityptr();
-  if (!myConnectivity->existConnectivity(MED_NODAL,MED_CELL) && myConnectivity->existConnectivity(MED_DESCENDING,MED_CELL))
-    {
-      os << endl << "SHOW CONNECTIVITY (DESCENDING) :" << endl;
-      int numberofelements;
-      const int * connectivity;
-      const int * connectivity_index;
-      myMesh.calculateConnectivity(MED_FULL_INTERLACE,MED_DESCENDING,MED_CELL);
-      try {
-       numberofelements = myMesh.getNumberOfElements(MED_CELL,MED_ALL_ELEMENTS);
-       connectivity =  myMesh.getConnectivity(MED_FULL_INTERLACE,MED_DESCENDING,MED_CELL,MED_ALL_ELEMENTS);
-       connectivity_index =  myMesh.getConnectivityIndex(MED_DESCENDING,MED_CELL);
-      }
-      catch (MEDEXCEPTION m) {
-       os << m.what() << endl;
-       exit (-1);
-      }
-      for (int j=0;j<numberofelements;j++) {
-       os << "Element "<<j+1<<" : ";
-       for (int k=connectivity_index[j];k<connectivity_index[j+1];k++)
-         os << connectivity[k-1]<<" ";
-       os << endl;
-      }
-    }
-  else
-    {
-      int numberoftypes = myMesh.getNumberOfTypes(MED_CELL);
-      const medGeometryElement  * types = myMesh.getTypes(MED_CELL);
-      os << endl << "SHOW CONNECTIVITY (NODAL) :" << endl;
-      for (int i=0; i<numberoftypes; i++) {
-       os << "For type " << types[i] << " : " << endl;
-       int numberofelements = myMesh.getNumberOfElements(MED_CELL,types[i]);
-       const int * connectivity =  myMesh.getConnectivity(MED_FULL_INTERLACE,MED_NODAL,MED_CELL,types[i]);
-       int numberofnodespercell = types[i]%100;
-       for (int j=0;j<numberofelements;j++){
-         os << "Element "<< j+1 <<" : ";
-         for (int k=0;k<numberofnodespercell;k++)
-           os << connectivity[j*numberofnodespercell+k]<<" ";
-         os << endl;
-       }
-      }
-    }
-
+  os << endl << "SHOW CONNECTIVITY  :" << endl;
+  os << *myMesh._connectivity << endl;
 
   medEntityMesh entity;
   os << endl << "SHOW FAMILIES :" << endl << endl;
@@ -457,8 +366,7 @@ ostream & operator<<(ostream &os, MESH &myMesh)
       if (k==3) entity = MED_FACE;
       if (k==4) entity = MED_EDGE;
       int numberoffamilies = myMesh.getNumberOfFamilies(entity);
-      using namespace MED_FR;
-      os << "NumberOfFamilies on "<< entNames[(MED_FR::med_entite_maillage) entity] <<" : "<<numberoffamilies<<endl;
+      os << "NumberOfFamilies on "<< entNames[entity] <<" : "<<numberoffamilies<<endl;
       using namespace MED_EN;
       for (int i=1; i<numberoffamilies+1;i++) 
        {
@@ -474,8 +382,7 @@ ostream & operator<<(ostream &os, MESH &myMesh)
       if (k==3) entity = MED_FACE;
       if (k==4) entity = MED_EDGE;
       int numberofgroups = myMesh.getNumberOfGroups(entity);
-      using namespace MED_FR;
-      os << "NumberOfGroups on "<< entNames[(MED_FR::med_entite_maillage) entity] <<" : "<<numberofgroups<<endl;
+      os << "NumberOfGroups on "<< entNames[entity] <<" : "<<numberofgroups<<endl;
       using namespace MED_EN;
       for (int i=1; i<numberofgroups+1;i++)
        {
@@ -629,7 +536,7 @@ SUPPORT * MESH::getBoundaryElements(medEntityMesh Entity)
     }
     numberOfGeometricType = theType.size() ;
     geometricType = new medGeometryElement[numberOfGeometricType] ;
-    const medGeometryElement *  allType = getTypes(Entity);
+    //const medGeometryElement *  allType = getTypes(Entity); !! UNUSZED VARIABLE !!
     numberOfGaussPoint = new int[numberOfGeometricType] ;
     geometricTypeNumber = new int[numberOfGeometricType] ; // not use, but initialized to nothing
     numberOfElements = new int[numberOfGeometricType] ;
@@ -706,7 +613,7 @@ FIELD<double>* MESH::getVolume(const SUPPORT * Support) const throw (MEDEXCEPTIO
     }
 
   int index;
-  FIELD<double>* Volume = new FIELD<double>::FIELD(Support,1);
+  FIELD<double>* Volume = new FIELD<double>(Support,1);
   //  double *volume = new double [length_values];
   Volume->setName("VOLUME");
   Volume->setDescription("cells volume");
@@ -1085,6 +992,8 @@ FIELD<double>* MESH::getVolume(const SUPPORT * Support) const throw (MEDEXCEPTIO
          throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Bad Support to get Volumes on it !"));
          break;
        }
+
+      if (!onAll) delete [] global_connectivity ;
     }
 
   return Volume;
@@ -1129,7 +1038,7 @@ FIELD<double>* MESH::getArea(const SUPPORT * Support) const throw (MEDEXCEPTION)
   int index;
   FIELD<double>* Area;
 
-  Area = new FIELD<double>::FIELD(Support,1);
+  Area = new FIELD<double>(Support,1);
   Area->setName("AREA");
   Area->setDescription("cells or faces area");
 
@@ -1289,6 +1198,8 @@ FIELD<double>* MESH::getArea(const SUPPORT * Support) const throw (MEDEXCEPTION)
          throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Bad Support to get Areas on it !"));
          break;
        }
+
+      if (!onAll) delete [] global_connectivity ;
     }
 
   Area->setValue(MED_FULL_INTERLACE,area);
@@ -1335,7 +1246,7 @@ FIELD<double>* MESH::getLength(const SUPPORT * Support) const throw (MEDEXCEPTIO
   int index;
   FIELD<double>* Length;
 
-  Length = new FIELD<double>::FIELD(Support,1);
+  Length = new FIELD<double>(Support,1);
   //  double *length = new double [length_values];
   Length->setValueType(MED_REEL64);
 
@@ -1406,6 +1317,8 @@ FIELD<double>* MESH::getLength(const SUPPORT * Support) const throw (MEDEXCEPTIO
          throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Bad Support to get Lengths on it !"));
          break;
        }
+
+      if (!onAll) delete [] global_connectivity ;
     }
 
   return Length;
@@ -1449,7 +1362,7 @@ FIELD<double>* MESH::getNormal(const SUPPORT * Support) const throw (MEDEXCEPTIO
 
   int index;
 
-  FIELD<double>* Normal = new FIELD<double>::FIELD(Support,dim_space);
+  FIELD<double>* Normal = new FIELD<double>(Support,dim_space);
   Normal->setName("NORMAL");
   Normal->setDescription("cells or faces normal");
   for (int k=1;k<=dim_space;k++) {
@@ -1523,7 +1436,7 @@ FIELD<double>* MESH::getNormal(const SUPPORT * Support) const throw (MEDEXCEPTIO
                int N2 = global_connectivity[tria_index+1]-1;
                int N3 = global_connectivity[tria_index+2]-1;
 
-               double xarea;
+               //double xarea; !! UNUSED VARIABLE !!
                double x1 = coord[dim_space*N1];
                double x2 = coord[dim_space*N2];
                double x3 = coord[dim_space*N3];
@@ -1591,12 +1504,19 @@ FIELD<double>* MESH::getNormal(const SUPPORT * Support) const throw (MEDEXCEPTIO
                              ((x4-x1)*(z2-z1) - (x2-x1)*(z4-z1)) +
                              ((x2-x1)*(y4-y1) - (x4-x1)*(y2-y1))*
                              ((x2-x1)*(y4-y1) - (x4-x1)*(y2-y1))) +
-                        sqrt(((y3-y2)*(z4-z3) - (y4-y3)*(z3-z2))*
-                             ((y3-y2)*(z4-z3) - (y4-y3)*(z3-z2)) +
-                             ((x4-x3)*(z2-z2) - (x3-x2)*(z4-z3))*
-                             ((x4-x3)*(z4-z2) - (x3-x2)*(z4-z3)) +
-                             ((x3-x2)*(y4-y3) - (x4-x3)*(y3-y2))*
-                             ((x3-x2)*(y4-y3) - (x4-x3)*(y3-y2))))/2.0;
+                        sqrt(((y4-y3)*(z2-z3) - (y2-y3)*(z4-z3))*
+                             ((y4-y3)*(z2-z3) - (y2-y3)*(z4-z3)) +
+                             ((x2-x3)*(z4-z3) - (x4-x3)*(z2-z3))*
+                             ((x2-x3)*(z4-z3) - (x4-x3)*(z2-z3)) +
+                             ((x4-x3)*(y2-y3) - (x2-x3)*(y4-y3))*
+                             ((x4-x3)*(y2-y3) - (x2-x3)*(y4-y3))))/2.0;
+
+//                      sqrt(((y3-y2)*(z4-z3) - (y4-y3)*(z3-z2))*
+//                           ((y3-y2)*(z4-z3) - (y4-y3)*(z3-z2)) +
+//                           ((x4-x3)*(z2-z2) - (x3-x2)*(z4-z3))*
+//                           ((x4-x3)*(z4-z2) - (x3-x2)*(z4-z3)) +
+//                           ((x3-x2)*(y4-y3) - (x4-x3)*(y3-y2))*
+//                           ((x3-x2)*(y4-y3) - (x4-x3)*(y3-y2))))/2.0;
 
                xnormal1 = xnormal1*xarea;
                xnormal2 = xnormal2*xarea;
@@ -1639,6 +1559,8 @@ FIELD<double>* MESH::getNormal(const SUPPORT * Support) const throw (MEDEXCEPTIO
          throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Bad Support to get Normals on it !"));
          break;
        }
+
+      if (!onAll) delete [] global_connectivity ;
     }
 
   Normal->setValue(MED_FULL_INTERLACE,normal);
@@ -1686,7 +1608,7 @@ FIELD<double>* MESH::getBarycenter(const SUPPORT * Support) const throw (MEDEXCE
   int index;
   FIELD<double>* Barycenter;
 
-  Barycenter = new FIELD<double>::FIELD(Support,dim_space);
+  Barycenter = new FIELD<double>(Support,dim_space);
   Barycenter->setName("BARYCENTER");
   Barycenter->setDescription("cells or faces barycenter");
 
@@ -2047,6 +1969,8 @@ FIELD<double>* MESH::getBarycenter(const SUPPORT * Support) const throw (MEDEXCE
          throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Bad Support to get a barycenter on it (in fact unknown type) !"));
          break;
        }
+
+      if (!onAll) delete [] global_connectivity ;
     }
 
   Barycenter->setValue(MED_FULL_INTERLACE,barycenter);
@@ -2063,24 +1987,35 @@ FIELD<double>* MESH::getBarycenter(const SUPPORT * Support) const throw (MEDEXCE
 //purpose  : if this->_isAGrid, assure that _coordinate is filled
 //=======================================================================
 
-inline void MESH::checkGridFillCoords() const
-{
-  if (_isAGrid)
-    ((GRID *) this)->fillCoordinates();
-}
+// inline void MESH::checkGridFillCoords() const
+// {
+//   if (_isAGrid)
+//     ((GRID *) this)->fillCoordinates();
+// }
 
 //=======================================================================
 //function : checkGridFillConnectivity
 //purpose  : if this->_isAGrid, assure that _connectivity is filled
 //=======================================================================
 
-inline void MESH::checkGridFillConnectivity() const
+// inline void MESH::checkGridFillConnectivity() const
+// {
+//   if (_isAGrid)
+//     ((GRID *) this)->fillConnectivity();
+// }
+
+bool MESH::isEmpty() const 
 {
-  if (_isAGrid)
-    ((GRID *) this)->fillConnectivity();
+    bool notempty = _name != "NOT DEFINED"                || _coordinate != NULL           || _connectivity != NULL ||
+                _spaceDimension !=MED_INVALID || _meshDimension !=MED_INVALID  || 
+                _numberOfNodes !=MED_INVALID  || _groupNode.size() != 0   || 
+                _familyNode.size() != 0       || _groupCell.size() != 0   || 
+                _familyCell.size() != 0       || _groupFace.size() != 0   || 
+                _familyFace.size() != 0       || _groupEdge.size() != 0   || 
+                _familyEdge.size() != 0       || _isAGrid != 0 ;
+    return !notempty;
 }
 
-
 void MESH::read(int index)  
 { 
   const char * LOC = "MESH::read(int index=0) : ";
@@ -2097,8 +2032,8 @@ void MESH::read(int index)
                                      << _drivers.size() 
                                      )
                           );
-  if (_isAGrid)
-    ((GRID *) this)->fillMeshAfterRead();
+//   if (_isAGrid)
+//     ((GRID *) this)->fillMeshAfterRead();
 
   END_OF(LOC);
 }
@@ -2220,7 +2155,7 @@ SUPPORT * MESH::getSkin(const SUPPORT * Support3D) throw (MEDEXCEPTION)
     }
     numberOfGeometricType = theType.size() ;
     geometricType = new medGeometryElement[numberOfGeometricType] ;
-    const medGeometryElement *  allType = getTypes(MED_FACE);
+    //const medGeometryElement *  allType = getTypes(MED_FACE); !! UNUSED VARIABLE !!
     numberOfGaussPoint = new int[numberOfGeometricType] ;
     geometricTypeNumber = new int[numberOfGeometricType] ; // not use, but initialized to nothing
     numberOfEntities = new int[numberOfGeometricType] ;
@@ -2260,3 +2195,472 @@ SUPPORT * MESH::getSkin(const SUPPORT * Support3D) throw (MEDEXCEPTION)
   return mySupport ;
  
 }
+
+/*!
+  return a SUPPORT pointer on the union of all SUPPORTs in Supports.
+  You should delete this pointer after use to avoid memory leaks.
+*/
+SUPPORT * MESH::mergeSupports(const vector<SUPPORT *> Supports) const throw (MEDEXCEPTION)
+{
+  const char * LOC = "MESH:::mergeSupports(const vector<SUPPORT *> ) : " ;
+  BEGIN_OF(LOC) ;
+
+  SUPPORT * returnedSupport;
+  string returnedSupportName;
+  string returnedSupportDescription;
+  char * returnedSupportNameChar;
+  char * returnedSupportDescriptionChar;
+  int size = Supports.size();
+
+  if (size == 1)
+    {
+      MESSAGE(LOC <<" there is only one SUPPORT in the argument list, the method return a copy of this object !");
+      SUPPORT * obj = const_cast <SUPPORT *> (Supports[0]);
+
+      returnedSupport = new SUPPORT(*obj);
+
+      int lenName = strlen((Supports[0]->getName()).c_str()) + 8 + 1;
+      int lenDescription = strlen((Supports[0]->getDescription()).c_str()) + 8 + 1;
+
+      returnedSupportNameChar = new char[lenName];
+      returnedSupportDescriptionChar = new char[lenDescription];
+
+      returnedSupportNameChar = strcpy(returnedSupportNameChar,"Copy of ");
+      returnedSupportNameChar = strcat(returnedSupportNameChar,(Supports[0]->getName()).c_str());
+      returnedSupportDescriptionChar = strcpy(returnedSupportDescriptionChar,"Copy of ");
+      returnedSupportDescriptionChar = strcat(returnedSupportDescriptionChar,
+                                             (Supports[0]->getDescription()).c_str());
+
+      returnedSupportName = string(returnedSupportNameChar);
+      returnedSupportDescription = string(returnedSupportDescriptionChar);
+
+      returnedSupport->setName(returnedSupportName);
+      returnedSupport->setDescription(returnedSupportDescription);
+
+      delete [] returnedSupportNameChar;
+      delete [] returnedSupportDescriptionChar;
+    }
+  else
+    {
+      SUPPORT * obj = const_cast <SUPPORT *> (Supports[0]);
+      returnedSupport = new SUPPORT(*obj);
+
+      int lenName = strlen((Supports[0]->getName()).c_str()) + 9 + 1;
+      int lenDescription = strlen((Supports[0]->getDescription()).c_str()) + 9 + 1;
+
+      for(int i = 1;i<size;i++)
+       {
+         obj = const_cast <SUPPORT *> (Supports[i]);
+         returnedSupport->blending(obj);
+
+         if (i == (size-1))
+           {
+             lenName = lenName + 5 + strlen((Supports[i]->getName()).c_str());
+             lenDescription = lenDescription + 5 +
+               strlen((Supports[i]->getDescription()).c_str());
+           }
+         else
+           {
+             lenName = lenName + 2 + strlen((Supports[i]->getName()).c_str());
+             lenDescription = lenDescription + 2 +
+               strlen((Supports[i]->getDescription()).c_str());
+           }
+       }
+
+      returnedSupportNameChar = new char[lenName];
+      returnedSupportDescriptionChar = new char[lenDescription];
+
+      returnedSupportNameChar = strcpy(returnedSupportNameChar,"Merge of ");
+      returnedSupportDescriptionChar = strcpy(returnedSupportDescriptionChar,"Merge of ");
+
+      returnedSupportNameChar = strcat(returnedSupportNameChar,(Supports[0]->getName()).c_str());
+      returnedSupportDescriptionChar = strcat(returnedSupportDescriptionChar,
+                                             (Supports[0]->getDescription()).c_str());
+
+      for(int i = 1;i<size;i++)
+       {
+         if (i == (size-1))
+           {
+             returnedSupportNameChar = strcat(returnedSupportNameChar," and ");
+             returnedSupportDescriptionChar = strcat(returnedSupportDescriptionChar," and ");
+
+             returnedSupportNameChar = strcat(returnedSupportNameChar,
+                                              (Supports[i]->getName()).c_str());
+             returnedSupportDescriptionChar = strcat(returnedSupportDescriptionChar,
+                                                     (Supports[i]->getDescription()).c_str());
+           }
+         else
+           {
+             returnedSupportNameChar = strcat(returnedSupportNameChar,", ");
+             returnedSupportNameChar = strcat(returnedSupportNameChar,
+                                              (Supports[i]->getName()).c_str());
+
+             returnedSupportDescriptionChar = strcat(returnedSupportDescriptionChar,", ");
+             returnedSupportDescriptionChar = strcat(returnedSupportDescriptionChar,
+                                                     (Supports[i]->getDescription()).c_str());
+           }
+       }
+
+      returnedSupportName = string(returnedSupportNameChar);
+      returnedSupport->setName(returnedSupportName);
+
+      returnedSupportDescription = string(returnedSupportDescriptionChar);
+      returnedSupport->setDescription(returnedSupportDescription);
+
+      delete [] returnedSupportNameChar;
+      delete [] returnedSupportDescriptionChar;
+    }
+
+  END_OF(LOC) ;
+  return returnedSupport;
+}
+
+/*!
+  return a SUPPORT pointer on the intersection of all SUPPORTs in Supports.
+  The (SUPPORT *) NULL pointer is returned if the intersection is empty.
+  You should delete this pointer after use to avois memory leaks.
+*/
+SUPPORT * MESH::intersectSupports(const vector<SUPPORT *> Supports) const throw (MEDEXCEPTION)
+{
+  const char * LOC = "MESH:::intersectSupports(const vector<SUPPORT *> ) : " ;
+  BEGIN_OF(LOC) ;
+
+  SUPPORT * returnedSupport;
+  string returnedSupportName;
+  string returnedSupportDescription;
+  char * returnedSupportNameChar;
+  char * returnedSupportDescriptionChar;
+  int size = Supports.size();
+
+  if (size == 1)
+    {
+      MESSAGE(LOC <<" there is only one SUPPORT in the argument list, the method return a copy of this object !");
+      SUPPORT * obj = const_cast <SUPPORT *> (Supports[0]);
+
+      returnedSupport = new SUPPORT(*obj);
+
+      int lenName = strlen((Supports[0]->getName()).c_str()) + 8 + 1;
+      int lenDescription = strlen((Supports[0]->getDescription()).c_str()) + 8 + 1;
+
+      returnedSupportNameChar = new char[lenName];
+      returnedSupportDescriptionChar = new char[lenDescription];
+
+      returnedSupportNameChar = strcpy(returnedSupportNameChar,"Copy of ");
+      returnedSupportNameChar = strcat(returnedSupportNameChar,(Supports[0]->getName()).c_str());
+      returnedSupportDescriptionChar = strcpy(returnedSupportDescriptionChar,"Copy of ");
+      returnedSupportDescriptionChar = strcat(returnedSupportDescriptionChar,
+                                             (Supports[0]->getDescription()).c_str());
+
+      returnedSupportName = string(returnedSupportNameChar);
+      returnedSupportDescription = string(returnedSupportDescriptionChar);
+
+      returnedSupport->setName(returnedSupportName);
+      returnedSupport->setDescription(returnedSupportDescription);
+
+      delete [] returnedSupportNameChar;
+      delete [] returnedSupportDescriptionChar;
+    }
+  else
+    {
+      SUPPORT * obj = const_cast <SUPPORT *> (Supports[0]);
+      returnedSupport = new SUPPORT(*obj);
+
+      int lenName = strlen((Supports[0]->getName()).c_str()) + 16 + 1;
+      int lenDescription = strlen((Supports[0]->getDescription()).c_str()) + 16 + 1;
+
+      for(int i = 1;i<size;i++)
+       {
+         obj = const_cast <SUPPORT *> (Supports[i]);
+         returnedSupport->intersecting(obj);
+
+         if (i == (size-1))
+           {
+             lenName = lenName + 5 + strlen((Supports[i]->getName()).c_str());
+             lenDescription = lenDescription + 5 +
+               strlen((Supports[i]->getDescription()).c_str());
+           }
+         else
+           {
+             lenName = lenName + 2 + strlen((Supports[i]->getName()).c_str());
+             lenDescription = lenDescription + 2 +
+               strlen((Supports[i]->getDescription()).c_str());
+           }
+       }
+
+      if(returnedSupport != (SUPPORT *) NULL)
+       {
+         returnedSupportNameChar = new char[lenName];
+         returnedSupportDescriptionChar = new char[lenDescription];
+
+         returnedSupportNameChar = strcpy(returnedSupportNameChar,
+                                          "Intersection of ");
+         returnedSupportDescriptionChar =
+           strcpy(returnedSupportDescriptionChar,"Intersection of ");
+
+         returnedSupportNameChar = strcat(returnedSupportNameChar,
+                                          (Supports[0]->getName()).c_str());
+         returnedSupportDescriptionChar =
+           strcat(returnedSupportDescriptionChar,
+                  (Supports[0]->getDescription()).c_str());
+
+         for(int i = 1;i<size;i++)
+           {
+             if (i == (size-1))
+               {
+                 returnedSupportNameChar = strcat(returnedSupportNameChar,
+                                                  " and ");
+                 returnedSupportDescriptionChar =
+                   strcat(returnedSupportDescriptionChar," and ");
+
+                 returnedSupportNameChar =
+                   strcat(returnedSupportNameChar,
+                          (Supports[i]->getName()).c_str());
+                 returnedSupportDescriptionChar =
+                   strcat(returnedSupportDescriptionChar,
+                          (Supports[i]->getDescription()).c_str());
+               }
+             else
+               {
+                 returnedSupportNameChar = strcat(returnedSupportNameChar,
+                                                  ", ");
+                 returnedSupportNameChar =
+                   strcat(returnedSupportNameChar,
+                          (Supports[i]->getName()).c_str());
+
+                 returnedSupportDescriptionChar =
+                   strcat(returnedSupportDescriptionChar,", ");
+                 returnedSupportDescriptionChar =
+                   strcat(returnedSupportDescriptionChar,
+                          (Supports[i]->getDescription()).c_str());
+               }
+           }
+
+         returnedSupportName = string(returnedSupportNameChar);
+         returnedSupport->setName(returnedSupportName);
+
+         returnedSupportDescription = string(returnedSupportDescriptionChar);
+         returnedSupport->setDescription(returnedSupportDescription);
+
+         delete [] returnedSupportNameChar;
+         delete [] returnedSupportDescriptionChar;
+       }
+    }
+
+  END_OF(LOC) ;
+  return returnedSupport;
+}
+
+
+// internal helper type
+struct _cell
+{
+    //int number;
+    std::vector<int> groups;
+    MED_EN::medGeometryElement geometricType;
+};
+
+// Create families from groups
+void MESH::createFamilies() 
+{
+    int nbFam=0; // count the families we create, used as identifier ???????????
+
+    int idFamNode = 0; // identifier for node families
+    int idFamElement = 0; // identifier for cell, face or edge families
+
+    // Main loop on mesh's entities
+    for (medEntityMesh entity=MED_CELL; entity!=MED_ALL_ENTITIES; ++entity)
+    {
+       int numberofgroups = getNumberOfGroups(entity);
+       if(!numberofgroups)
+           continue; // no groups for this entity
+       
+       vector< vector<FAMILY*> > whichFamilyInGroup(numberofgroups); // this container is used to update groups at the end
+
+       // make myFamilies points to the member corresponding to entity
+       vector<FAMILY*>* myFamilies;
+       switch ( entity )
+       {
+           case MED_CELL :
+               myFamilies = & _familyCell;
+               break;
+           case MED_FACE :
+               myFamilies = & _familyFace;
+               break;
+           case MED_EDGE :
+               myFamilies = & _familyEdge;
+               break;
+           case MED_NODE :
+               myFamilies = & _familyNode;
+               break;
+       }
+       
+       vector<GROUP*> myGroups=getGroups(entity); // get a copy of the groups ptr for the entity
+       // get a copy of the (old) family ptrs before clearing
+       vector<FAMILY*> myOldFamilies=getFamilies(entity); 
+       myFamilies->clear();
+
+
+       // 1 - Create a vector containing for each cell (of the entity) an information structure
+       //     giving geometric type and the groups it belong to
+
+       med_int numberOfTypes=getNumberOfTypes(entity);
+       const int * index=getGlobalNumberingIndex(entity);
+       const medGeometryElement* geometricTypes=_connectivity->getGeometricTypes(entity); // pb avec entity=MED_NODE???
+       med_int numberOfCells=index[numberOfTypes]-1;  // total number of cells for that entity
+       SCRUTE(numberOfTypes);
+       SCRUTE(numberOfCells);
+       vector< _cell > tab_cell(numberOfCells);
+       for(med_int t=0; t!=numberOfTypes; ++t)
+           for(int n=index[t]-1; n!=index[t+1]-1; ++n)
+               tab_cell[n].geometricType=geometricTypes[t];
+
+       
+       // 2 - Scan cells in groups and update in tab_cell the container of groups a cell belong to
+       
+       for (unsigned g=0; g!=myGroups.size(); ++g)
+       {
+           // scan cells that belongs to the group
+           const int* groupCells=myGroups[g]->getnumber()->getValue();
+           int nbCells=myGroups[g]->getnumber()->getLength();
+           for(int c=0; c!=nbCells; ++c)
+               tab_cell[groupCells[c]-1].groups.push_back(g);
+       }
+
+
+       // 3 - Scan the cells vector, genarate family name, and create a map associating the family names 
+       //     whith the vector of contained cells
+       
+       map< string,vector<int> > tab_families;
+       map< string,vector<int> >::iterator fam;
+       for(int n=0; n!=numberOfCells; ++n)
+       {
+           ostringstream key; // to generate the name of the family
+           key << "FAM";
+           if(tab_cell[n].groups.empty()) // this cell don't belong to any group
+               key << "_NONE" << entity;
+           
+           for(vector<int>::const_iterator it=tab_cell[n].groups.begin(); it!=tab_cell[n].groups.end(); ++it)
+           {
+               string groupName=myGroups[*it]->getName();
+               if(groupName.empty())
+                   key << "_G" << *it;
+               else
+                   key << "_" << groupName;
+           }
+           
+           tab_families[key.str()].push_back(n+1); // fill the vector of contained cells associated whith the family
+       /*    fam = tab_families.find(key.str());
+           if( fam != tab_families.end())
+               fam->second.push_back(n+1); // +1 : convention Fortran de MED
+           else
+           {
+               vector<int> newfamily;
+               newfamily.push_back(n+1); // +1 : convention Fortran de MED
+               tab_families.insert(make_pair(key.str(),newfamily));
+           }*/
+       }
+
+
+       // 4 - Scan the family map, create MED Families, check if it already exist.
+       
+       for( fam=tab_families.begin(); fam!=tab_families.end(); ++fam)
+       {
+           vector<medGeometryElement> tab_types_geometriques;
+           medGeometryElement geometrictype=MED_NONE;
+           vector<int> tab_index_types_geometriques;
+           vector<int> tab_nombres_elements;
+
+           // scan family cells and fill the tab that are needed by the create a MED FAMILY
+           for( int i=0; i!=fam->second.size(); ++i) 
+           {
+               int ncell=fam->second[i]-1; 
+               if(tab_cell[ncell].geometricType != geometrictype)
+               {
+                   // new geometric type -> we store it and complete index tabs
+                   if(!tab_index_types_geometriques.empty())
+                       tab_nombres_elements.push_back(i+1-tab_index_types_geometriques.back());
+                   tab_types_geometriques.push_back( (geometrictype=tab_cell[ncell].geometricType));
+                   tab_index_types_geometriques.push_back(i+1);
+               }
+           }
+           // store and complete index tabs for the last geometric type
+           tab_nombres_elements.push_back(fam->second.size()+1-tab_index_types_geometriques.back());
+           tab_index_types_geometriques.push_back(fam->second.size()+1);
+
+           // create a empty MED FAMILY and fill it with the tabs we constructed
+           FAMILY* newFam = new FAMILY();
+           newFam->setTotalNumberOfElements(fam->second.size());
+           newFam->setName(fam->first);
+           newFam->setMesh(this);
+           newFam->setNumberOfGeometricType(tab_types_geometriques.size());
+           newFam->setGeometricType(&tab_types_geometriques[0]); // we know the tab is not empy
+           newFam->setNumberOfElements(&tab_nombres_elements[0]);
+           newFam->setNumber(&tab_index_types_geometriques[0],&fam->second[0]);
+           newFam->setEntity(entity);
+           newFam->setAll(false);
+
+           int idFam = 0;
+
+           switch ( entity )
+             {
+             case MED_NODE :
+               ++idFamNode;
+               idFam = idFamNode;
+               break;
+             case MED_CELL:
+               ++idFamElement;
+               idFam = -idFamElement;
+               break;
+             case MED_FACE :
+               ++idFamElement;
+               idFam = -idFamElement;
+               break;
+             case MED_EDGE :
+               ++idFamElement;
+               idFam = -idFamElement;
+               break;
+             }
+
+           newFam->setIdentifier(idFam);
+
+           // Update links between families and groups
+
+           int ncell1=fam->second[0]-1;  // number of first cell in family
+           int numberOfGroups=tab_cell[ncell1].groups.size(); // number of groups in the family
+           if(numberOfGroups)
+           {
+               newFam->setNumberOfGroups(numberOfGroups);
+               string * groupNames=new string[numberOfGroups];
+
+               // iterate on the groups the family belongs to
+               vector<int>::const_iterator it=tab_cell[ncell1].groups.begin();
+               for(int ng=0 ; it!=tab_cell[ncell1].groups.end(); ++it, ++ng)
+               {
+                   whichFamilyInGroup[*it].push_back(newFam);
+                   groupNames[ng]=myGroups[*it]->getName();
+               }
+               newFam->setGroupsNames(groupNames);
+           }
+
+           int sizeOfFamVect = myFamilies->size();
+
+           MESSAGE("  MESH::createFamilies() entity " << entity << " size " << sizeOfFamVect);
+
+           myFamilies->push_back(newFam);
+       }
+
+       // delete old families
+       for (int i=0;i<myOldFamilies.size();i++)
+           delete myOldFamilies[i] ;
+
+       // update references in groups
+       for (int i=0;i<myGroups.size();i++)
+       {
+           myGroups[i]->setNumberOfFamilies(whichFamilyInGroup[i].size());
+           myGroups[i]->setFamilies(whichFamilyInGroup[i]);
+       }
+
+    // re-scan the cells vector, and fill the family vector with cells.
+    // creation of support, check if it already exist.
+    }
+}