diff --git a/Common/OpenFile.cpp b/Common/OpenFile.cpp
index 80360803c32dd200264662ec46b08c853318a10e..e20d694399bfe032302fdb6eb643627df74636b0 100644
--- a/Common/OpenFile.cpp
+++ b/Common/OpenFile.cpp
@@ -520,7 +520,7 @@ int MergeFile(const std::string &fileName, bool warnIfMissing, bool setBoundingB
       status = GModel::readGEO(fileName);
     }
   }
-
+  
   ComputeMaxEntityNum();
   if(setBoundingBox) SetBoundingBox();
   CTX::instance()->geom.draw = 1;
diff --git a/Geo/CMakeLists.txt b/Geo/CMakeLists.txt
index ecfd656e588526d43ad5c4427716e551268d700c..1c2dc82e20a76cb7c647264138c52cc536bcc8ea 100644
--- a/Geo/CMakeLists.txt
+++ b/Geo/CMakeLists.txt
@@ -21,6 +21,7 @@ set(SRC
   ACISEdge.cpp
   ACISFace.cpp
   GModel.cpp
+  GModelCreateTopologyFromMesh.cpp
     GModelVertexArrays.cpp
     GModelFactory.cpp
     GModelIO_GEO.cpp GModelIO_ACIS.cpp GModelIO_OCC.cpp GModelIO_TOCHNOG.cpp
diff --git a/Geo/GEdge.h b/Geo/GEdge.h
index e0db7f1cb004995a780aef3536a5b7fbe34b598c..d88bbe461a9ca235b9a1c3e723fe985cdb460de3 100644
--- a/Geo/GEdge.h
+++ b/Geo/GEdge.h
@@ -48,6 +48,8 @@ class GEdge : public GEntity{
   virtual void deleteMesh();
 
   // get the start/end vertices of the edge
+  void setBeginVertex(GVertex *gv) { v0=gv; }
+  void setEndVertex(GVertex *gv)  { v1=gv; }
   virtual GVertex *getBeginVertex() const { return v0; }
   virtual GVertex *getEndVertex() const { return v1; }
 
diff --git a/Geo/GFace.h b/Geo/GFace.h
index f394f44fbe347a9b7fdfaef9d89616484a29ac74..b0a89bd11f6bd90666338396b99ba70faf4c321e 100644
--- a/Geo/GFace.h
+++ b/Geo/GFace.h
@@ -112,6 +112,7 @@ class GFace : public GEntity{
 
   // edges that bound the face
   virtual std::list<GEdge*> edges() const { return l_edges; }
+  inline void set(const std::list<GEdge*> f) { l_edges= f; }
   virtual std::list<int> edgeOrientations() const { return l_dirs; }
   inline bool containsEdge (int iEdge) const
   {
diff --git a/Geo/GModel.cpp b/Geo/GModel.cpp
index 4d61c62ccc84f3e14224c1207f0109d7cd841543..1aac4eb9a25f1f9d50325fc04e7e83dd2c7249b7 100644
--- a/Geo/GModel.cpp
+++ b/Geo/GModel.cpp
@@ -42,6 +42,7 @@
 #include "meshGEdge.h"
 #include "meshGFace.h"
 #include "meshGRegion.h"
+#include "GModelCreateTopologyFromMesh.h"
 
 #if defined(HAVE_MESH)
 #include "Field.h"
@@ -2251,15 +2252,26 @@ void GModel::makeDiscreteFacesSimplyConnected()
   Msg::Debug("Done making discrete faces simply connected");
 }
 
+
 void GModel::createTopologyFromMesh(int ignoreHoles)
 {
   Msg::StatusBar(true, "Creating topology from mesh...");
   double t1 = Cpu();
-
   removeDuplicateMeshVertices(CTX::instance()->geom.tolerance);
   makeDiscreteRegionsSimplyConnected();
   makeDiscreteFacesSimplyConnected();
 
+  // // TEST !!!!!!!!
+  // if (1)
+  // {
+  //   createTopologyFromMeshNew (this);
+  //   double t2 = Cpu();
+  //   Msg::StatusBar(true, "Done creating topology from mesh (%g s)", t2 - t1);
+  //   return;
+  // }
+  
+
+  
   // create topology for all discrete regions
   std::vector<discreteRegion*> discRegions;
   for(riter it = firstRegion(); it != lastRegion(); it++)
diff --git a/Geo/GModelCreateTopologyFromMesh.cpp b/Geo/GModelCreateTopologyFromMesh.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..24d2cfbe9d5c8e7686c33a0f2680d9f99c591528
--- /dev/null
+++ b/Geo/GModelCreateTopologyFromMesh.cpp
@@ -0,0 +1,328 @@
+#include <map> 
+#include "GModelCreateTopologyFromMesh.h"
+#include "GModel.h"
+#include "Geo.h"
+#include "discreteFace.h"
+#include "discreteEdge.h"
+#include "MPoint.h"
+#include "MVertex.h"
+#include "MLine.h"
+#include "MEdge.h"
+#include "MFace.h"
+#include "MTriangle.h"
+#include "MQuadrangle.h"
+
+/*
+  Assumptions :       
+      --> The input mesh is potentially (partially) coloured 
+      --> 
+*/
+
+template <class T>
+class myBundle {
+public : 
+  std::set<T> stuff;
+  void insert (T t) {stuff.insert(t);}
+  void print() const {
+    printf("bundle of %ld entities\n",stuff.size());
+    for (typename std::set<T>::iterator it = stuff.begin(); it != stuff.end() ; ++it){
+      printf ("%d ",(*it)->tag());
+    }
+    printf("\n");
+  }
+  bool operator  < (const myBundle<T> & other) const{
+    if (other.stuff.size() < stuff.size()) return true;
+    if (other.stuff.size() > stuff.size()) return false;
+    typename std::set<T>::const_iterator it  = stuff.begin();
+    typename std::set<T>::const_iterator it2 = other.stuff.begin();
+    for ( ; it != stuff.end() ; ++it, ++it2){
+      if (*it < *it2) return true;
+      if (*it > *it2) return false;
+    }
+    return false;
+  }  
+};
+
+
+void createTopologyFromMesh1D ( GModel *gm ) {
+  std::map<MVertex*, myBundle<GEdge*> > _temp;
+  std::set<myBundle<GEdge*> > _bundles;
+  std::map<MVertex*, GVertex*> _existingVertices;
+  std::map<GEdge*, std::set<GVertex*> > _topology;
+  
+  // create an inverse dictionnary for existing edges
+  for(GModel::viter it = gm->firstVertex(); it != gm->lastVertex(); it++) {
+    _existingVertices[(*it)->mesh_vertices[0]] = *it;
+  }    
+
+  //  printf("%ud mesh vertices are already classified\n",_existingVertices.size());
+
+  
+  for(GModel::eiter it = gm->firstEdge(); it != gm->lastEdge(); it++) {
+    for (int i=0;i<(*it)->lines.size();i++){
+      MLine *e = (*it)->lines[i];
+      for (int j=0;j<2;j++){
+	MVertex* v = e->getVertex(j);
+	GVertex *gv = _existingVertices[v];
+	if (gv)
+	  _topology[*it].insert(gv);
+	else
+	  _temp[v].insert(*it);
+      }      
+    }    
+  }
+
+  //  printf("%d new mesh vertices \n",_temp.size());
+
+  // create unique instances
+  for (std::map<MVertex*, myBundle<GEdge*> >::iterator it = _temp.begin(); it != _temp.end() ; it++){
+    _bundles.insert (it->second);
+  }
+
+  //  printf("%d bundles\n",_bundles.size());
+
+  
+  // create discrete edges
+
+  std::map <myBundle<GEdge*> , GVertex *> _e2v;
+  {
+    std::set<myBundle<GEdge*> >::iterator it = _bundles.begin();
+    for (; it != _bundles.end(); ++it) {
+      if (it->stuff.size() > 1) {
+	discreteVertex *dv = new discreteVertex (  gm , NEWPOINT());    
+	_e2v [*it] = dv;
+	for (std::set<GEdge*>::iterator it2 = it->stuff.begin(); it2 != it->stuff.end() ; ++it2){
+	  _topology[*it2].insert(dv);
+	}
+      }
+    }
+  }
+
+  //  create the 0D mesh
+  {
+    std::map<MVertex*, myBundle<GEdge*> > :: iterator it = _temp.begin();
+    for (; it != _temp.end(); ++it) {
+      if (it->second.stuff.size() > 1) {
+	MVertex *v = it->first;
+	GVertex *gv = _e2v [it->second];
+	gv->mesh_vertices.push_back(v);
+      }
+    }
+  }
+
+  // create Edge 2 Vertex topology
+  {
+    std::map<GEdge*, std::set<GVertex*> >::iterator it =  _topology.begin();
+    for ( ; it != _topology.end() ; ++it){
+      std::list<GVertex*> l ; l.insert (l.begin(), it->second.begin(), it->second.end());
+      if (l.size() == 0){
+      }
+      else if (l.size() <= 2){
+	std::list<GVertex*>::iterator it2 = l.begin();
+	it->first->setBeginVertex(*it2);
+	if (l.size() == 2)++it2;
+	it->first->setEndVertex(*it2);	
+      }
+      else {
+	Msg::Error ("FIXME : create simply connected edges in CreateTopology");
+      }
+      
+      for (std::list<GVertex*>::iterator it2 =  l.begin() ; it2 != l.end() ; ++it2)(*it2)->addEdge(it->first);      
+    }
+  }
+
+
+  // NICE :-)
+}
+
+void createTopologyFromMesh2D ( GModel *gm ) {
+
+  std::map<MEdge, myBundle<GFace*>, Less_Edge > _temp;
+  std::set<myBundle<GFace*> > _bundles;
+  std::map<MEdge, GEdge*, Less_Edge> _existingEdges;
+  std::map<GFace*, std::set<GEdge*> > _topology;
+  
+  // create an inverse dictionnary for existing edges
+  for(GModel::eiter it = gm->firstEdge(); it != gm->lastEdge(); it++) {
+    for (int i = 0; i < (*it)->lines.size(); i++)_existingEdges[(*it)->lines[i]->getEdge(0)] = *it;
+  }    
+
+  //  printf("%d mesh edges aere already classified\n",_existingEdges.size());
+
+  // create inverse dictionary for all other edges
+  for(GModel::fiter it = gm->firstFace(); it != gm->lastFace(); it++) {
+    for (int i=0;i<(*it)->getNumMeshElements();i++){
+      MElement *e = (*it)->getMeshElement(i);
+      for (int j=0;j<e->getNumEdges();j++){
+	MEdge ed = e->getEdge(j);
+	GEdge *ge = _existingEdges[ed];
+	if (ge)
+	  _topology[*it].insert(ge);
+	else 
+	  _temp[ed].insert(*it);
+      }      
+    }    
+  }
+
+  // create unique instances
+  for (std::map<MEdge, myBundle<GFace*>, Less_Face >::iterator it = _temp.begin(); it != _temp.end() ; it++){
+    _bundles.insert (it->second);
+  }
+
+  // create discrete edges  
+  std::map <myBundle<GFace*> , GEdge *> _f2e;
+  {
+    std::set<myBundle<GFace*> >::iterator it = _bundles.begin();
+    for (; it != _bundles.end(); ++it) {
+      //      it->print();
+      if (it->stuff.size() > 1){
+	printf("creation of a new discrete edge !\n");
+	discreteEdge *de = new discreteEdge (  gm , NEWREG(), NULL, NULL);    
+	_f2e [*it] = de;
+	for (std::set<GFace*>::iterator it2 = it->stuff.begin(); it2 != it->stuff.end();++it2)
+	  _topology[*it2].insert(de);
+      }
+    }
+  }
+
+  //  create the 1D mesh
+  {
+    std::map<MEdge, myBundle<GFace*>, Less_Edge > :: iterator it = _temp.begin();
+    for (; it != _temp.end(); ++it) {
+      if (it->second.stuff.size() > 1){
+	MEdge e = it->first;
+	GEdge *ge = _f2e [it->second];
+	// not yet bounded
+	MLine *l = new MLine (e.getVertex(0),e.getVertex(1));
+	ge->lines.push_back(l);
+	for (int i=0;i<e.getNumVertices ();i++)e.getVertex(i)->setEntity(ge);
+      }
+    }
+  }
+
+  // create Face 2 Edge topology
+  {
+    std::map<GFace*, std::set<GEdge*> >::iterator it =  _topology.begin();
+    for ( ; it != _topology.end() ; ++it){
+      std::list<GEdge*> l ; l.insert (l.begin(), it->second.begin(), it->second.end());
+      it->first->set(l);
+      //      printf("Face %d has %d edges\n",it->first->tag(), l.size());
+      for (std::list<GEdge*>::iterator it2 =  l.begin() ; it2 != l.end() ; ++it2)(*it2)->addFace(it->first);      
+    }
+  }
+
+  
+  // NICE :-)
+}
+
+/// ----------------------------------------------------------------
+/// ---------------   3D         -----------------------------------
+/// ----------------------------------------------------------------
+
+void createTopologyFromMesh3D ( GModel *gm ) {
+  
+  std::map<MFace, std::pair<GRegion*,GRegion*>, Less_Face > _temp;
+  std::set<std::pair<GRegion*,GRegion*> > _pairs;
+  std::map<MFace, GFace*, Less_Face> _existingFaces;
+  std::map<GRegion*, std::set<GFace*> > _topology;
+
+  // create an inverse dictionnary for existing faces
+  for(GModel::fiter it = gm->firstFace(); it != gm->lastFace(); it++) {
+    for (unsigned int i = 0; i < (*it)->triangles.size(); i++)_existingFaces[(*it)->triangles[i]->getFace(0)] = *it;
+    for (unsigned int i = 0; i < (*it)->quadrangles.size(); i++)_existingFaces[(*it)->quadrangles[i]->getFace(0)] = *it;
+  }    
+
+  //  printf("%d mesh faces aere already classified\n",_existingFaces.size());
+  
+  // create inverse dictionary for all other faces
+  for(GModel::riter it = gm->firstRegion(); it != gm->lastRegion(); it++) {
+    for (int i=0;i<(*it)->getNumMeshElements();i++){
+      MElement *e = (*it)->getMeshElement(i);
+      for (int j=0;j<e->getNumFaces();j++){
+	MFace f = e->getFace(j);
+	GFace *gf = _existingFaces[f];
+	if (gf){
+	  _topology[*it].insert(gf);
+	}
+	else  {
+	  std::map<MFace, std::pair<GRegion*,GRegion*>, Less_Face >::iterator itf = _temp.find(f);
+	  if (itf == _temp.end()){
+	    _temp[f] = std::make_pair ( (GRegion*)NULL, *it) ;
+	  }
+	  else {
+	    itf->second.first = *it ;
+	  }
+	}
+      }      
+    }
+  }
+  
+  //  printf("%d new mesh faces \n",_temp.size());
+
+  // create unique instances
+  for (std::map<MFace, std::pair<GRegion*,GRegion*>, Less_Face >::iterator it = _temp.begin(); it != _temp.end() ; it++){
+    _pairs.insert (std::make_pair (std::min (it->second.first, it->second.second),
+				   std::max (it->second.first, it->second.second)));
+  }    
+  
+  // create discrete faces
+  
+  //  printf("%d pairs of regions exist to create new GFaces \n",_pairs.size());
+
+  std::map <std::pair<GRegion*,GRegion*> , GFace *> _r2f;
+  {
+    std::set<std::pair<GRegion*,GRegion*> >::iterator it = _pairs.begin();
+    for (; it != _pairs.end(); ++it) {
+      if (it->first != it->second) {
+	printf("creating a new discrete face between %p and %p\n",it->first, it->second);
+	discreteFace *df = new discreteFace (  gm , NEWREG());    
+	_r2f [*it] = df;
+	if (it->first)_topology[it->first].insert(df);
+	if (it->second)_topology[it->second].insert(df);
+      }
+    }
+  }
+
+  //  add mesh faces in newly created GFaces
+  {
+    std::map<MFace, std::pair<GRegion*,GRegion*>, Less_Face > :: iterator it = _temp.begin();
+    for (; it != _temp.end(); ++it) {
+      if (it->second.first != it->second.second){
+	MFace f = it->first;      
+	GFace *gf = _r2f [it->second];
+	if (f.getNumVertices () == 3){
+	  MTriangle *t = new MTriangle (f.getVertex(0),f.getVertex(1),f.getVertex(2));
+	  gf->triangles.push_back(t);
+	}
+	else if (f.getNumVertices () == 4){
+	  MQuadrangle *q = new MQuadrangle (f.getVertex(0),f.getVertex(1),f.getVertex(2),f.getVertex(3));
+	  gf->quadrangles.push_back(q);	 
+	}
+	for (int i=0;i<f.getNumVertices ();i++)f.getVertex(i)->setEntity(gf);
+      }
+    }
+  }  
+  
+  // create Regions 2 Faces topology
+  {
+    std::map<GRegion*, std::set<GFace*> >::iterator it =  _topology.begin();
+    for ( ; it != _topology.end() ; ++it){
+      std::list<GFace*> l ; l.insert (l.begin(), it->second.begin(), it->second.end());
+      it->first->set(l);
+      //      printf("Region %d has %d adjacent faces\n",it->first->tag(), l.size());
+      for (std::list<GFace*>::iterator it2 =  l.begin() ; it2 != l.end() ; ++it2)(*it2)->addRegion(it->first);      
+    }
+  }
+  
+  // NICE :-)
+  
+}
+
+void createTopologyFromMeshNew ( GModel *gm ) {
+  const int dim = gm->getDim ();    
+  if (dim >= 3) createTopologyFromMesh3D (gm);
+  if (dim >= 2) createTopologyFromMesh2D (gm);
+  if (dim >= 1) createTopologyFromMesh1D (gm);
+  Msg::Info("createTopologyFromMeshNew (%d regions %d faces and %d edges)",gm->getNumRegions(),  gm->getNumFaces(), gm->getNumEdges());
+
+}
diff --git a/Geo/GModelCreateTopologyFromMesh.h b/Geo/GModelCreateTopologyFromMesh.h
new file mode 100644
index 0000000000000000000000000000000000000000..79a8ecf4f948a93ddff7f7394b552eda4492d664
--- /dev/null
+++ b/Geo/GModelCreateTopologyFromMesh.h
@@ -0,0 +1,5 @@
+#ifndef _CREATE_TOPOLOGY_FROM_MESH
+#define _CREATE_TOPOLOGY_FROM_MESH
+class GModel;
+void createTopologyFromMeshNew ( GModel *gm ) ;
+#endif
diff --git a/Geo/GModelIO_GEO.cpp b/Geo/GModelIO_GEO.cpp
index d34eb6120103bf8b4e44837abbb722af1aec62f9..39f64b3ee882a278bdc6f15dc9343e3fbc197ee4 100644
--- a/Geo/GModelIO_GEO.cpp
+++ b/Geo/GModelIO_GEO.cpp
@@ -42,7 +42,6 @@ int GModel::readGEO(const std::string &name)
 {
   ParseFile(name, true);
   int imported = GModel::current()->importGEOInternals();
-
   return imported;
 }
 
diff --git a/Geo/GModelIO_MSH.cpp b/Geo/GModelIO_MSH.cpp
index 04fe00a7ac6236e0a8fdf2f4a4964a8327094897..2e715cde930d28b465fba1f56a1641c0d3155d51 100644
--- a/Geo/GModelIO_MSH.cpp
+++ b/Geo/GModelIO_MSH.cpp
@@ -23,6 +23,7 @@
 #include "discreteEdge.h"
 #include "discreteFace.h"
 #include "discreteRegion.h"
+#include "GModelCreateTopologyFromMesh.h"
 
 static int readMSHPhysicals(FILE *fp, GEntity *ge)
 {
@@ -179,6 +180,7 @@ int GModel::readMSH(const std::string &name)
 
   double version = 0.;
   bool binary = false, swap = false, postpro = false;
+  bool topology = false;
   int minVertex = 0;
   std::map<int, std::vector<MElement*> > elements[11];
 
@@ -234,6 +236,7 @@ int GModel::readMSH(const std::string &name)
     // $Entities section
     else if(!strncmp(&str[1], "Entities", 8)) {
       readMSHEntities(fp, this);
+      topology = true;
     }
 
     // $Nodes section
@@ -444,6 +447,8 @@ int GModel::readMSH(const std::string &name)
     } while(str[0] != '$');
   }
 
+
+  
   // store the elements in their associated elementary entity. If the
   // entity does not exist, create a new (discrete) one.
   for(int i = 0; i < (int)(sizeof(elements) / sizeof(elements[0])); i++)
@@ -458,6 +463,9 @@ int GModel::readMSH(const std::string &name)
   else
     _storeVerticesInEntities(_vertexMapCache);
 
+  // if no topology is given, create one
+  if (!topology)createTopologyFromMeshNew (this);
+  
   _createGeometryOfDiscreteEntities() ;
 
   for(int i = 0; i < (int)(sizeof(elements) / sizeof(elements[0])); i++)
diff --git a/Geo/GModelIO_MSH2.cpp b/Geo/GModelIO_MSH2.cpp
index 2a6521750978b5e9ac697f75899d3f5022f52525..bcfae5b10618196feb1864e8bee3c8ec0b4531d5 100644
--- a/Geo/GModelIO_MSH2.cpp
+++ b/Geo/GModelIO_MSH2.cpp
@@ -26,6 +26,7 @@
 #include "GmshMessage.h"
 #include "Context.h"
 #include "OS.h"
+#include "GModelCreateTopologyFromMesh.h"
 
 #define FAST_ELEMENTS 1
 
@@ -687,6 +688,9 @@ int GModel::_readMSH2(const std::string &name)
   else
     _storeVerticesInEntities(vertexMap);
 
+  // if no topology is given, create one  
+  createTopologyFromMeshNew (this);
+
   // store the physical tags
   for(int i = 0; i < 4; i++)
     _storePhysicalTagsInEntities(i, physicals[i]);
diff --git a/Geo/GModelIO_OCC.cpp b/Geo/GModelIO_OCC.cpp
index 6b1e41365fb0111faa5e564870a1e74e1de6750c..92295867ee1b51acc402d65539eb9771d4414900 100644
--- a/Geo/GModelIO_OCC.cpp
+++ b/Geo/GModelIO_OCC.cpp
@@ -741,6 +741,7 @@ GRegion* OCC_Internals::addRegionToModel(GModel *model, TopoDS_Solid region)
   GRegion *gr = getOCCRegionByNativePtr(model, region);
   if(gr) return gr;
 
+  // FIXME THE PREVIOUS IMPLEMENTATION WAS BETTER FOR SOME USERS :-)
   buildShapeFromLists(region);
   model->destroy();
   buildLists();
diff --git a/Geo/GModelIO_STL.cpp b/Geo/GModelIO_STL.cpp
index a684d6e5dc6237285fe2f3a5e3bd20d3cc3bc02f..50abbcb315fe1bd3f6b681a7b37f5a717219a71f 100644
--- a/Geo/GModelIO_STL.cpp
+++ b/Geo/GModelIO_STL.cpp
@@ -12,6 +12,7 @@
 #include "MVertexRTree.h"
 #include "discreteFace.h"
 #include "StringUtils.h"
+#include "GModelCreateTopologyFromMesh.h"
 
 int GModel::readSTL(const std::string &name, double tolerance)
 {
@@ -176,6 +177,11 @@ int GModel::readSTL(const std::string &name, double tolerance)
   _associateEntityWithMeshVertices();
   _storeVerticesInEntities(vertices); // will delete unused vertices
 
+  // if no topology is given, create one
+  createTopologyFromMeshNew (this);
+
+  _createGeometryOfDiscreteEntities() ;
+
   fclose(fp);
   return 1;
 }
diff --git a/Mesh/Generator.cpp b/Mesh/Generator.cpp
index 4f14d5c3d21043f1d4d323b12610726c2752f4ca..be03cb69193ff3fc55bba0e2126f055bf9163ac4 100644
--- a/Mesh/Generator.cpp
+++ b/Mesh/Generator.cpp
@@ -915,6 +915,7 @@ void RecombineMesh(GModel *m)
 
 void GenerateMesh(GModel *m, int ask)
 {
+
   // ProfilerStart("gmsh.prof");
   if(CTX::instance()->lock) {
     Msg::Info("I'm busy! Ask me that later...");