diff --git a/Geo/GModelIO_CGNS.cpp b/Geo/GModelIO_CGNS.cpp
index 2cfaa986998ef1f5e59ef9cad993c103ed52595d..ff2b4d99c3d6b5f56c7734e67c0effb4c116ddde 100644
--- a/Geo/GModelIO_CGNS.cpp
+++ b/Geo/GModelIO_CGNS.cpp
@@ -279,6 +279,83 @@ static int to1D(int i, int j, int k, int max_i, int max_j, int max_k) {
   return k*max_i*max_j + j*max_i + i;
 }
 
+static int getIndicesQuad(int i1, int i2, int i3, int i4, 
+			  int j1, int j2, int j3, int j4,
+			  int k1, int k2, int k3, int k4,
+			  std::vector<int>& ind_i, std::vector<int>& ind_j, std::vector<int>& ind_k, int order, int f) {
+
+  static const int offset[6][4][3] = {
+    {{ 1, 1, 0}, { 1,-1, 0}, {-1,-1, 0}, {-1, 1, 0}},
+    {{ 1, 1 ,0}, {-1, 1, 0}, {-1,-1, 0}, { 1,-1, 0}},
+    {{ 1, 0, 1}, {-1, 0, 1}, {-1, 0,-1}, { 1, 0,-1}},
+    {{ 1, 0, 1}, { 1, 0,-1}, {-1, 0,-1}, {-1, 0, 1}},
+    {{ 0, 1, 1}, { 0, 1,-1}, { 0,-1,-1}, { 0,-1, 1}},
+    {{ 0, 1, 1}, { 0,-1, 1}, { 0,-1,-1}, { 0, 1,-1}}
+  };  
+
+  int added = 0;
+
+  if (order == 0) {
+    ind_i.push_back(i1); ind_j.push_back(j1); ind_k.push_back(k1);
+    return 1;
+  }
+
+  // corners
+  ind_i.push_back(i1); ind_j.push_back(j1); ind_k.push_back(k1);
+  ind_i.push_back(i2); ind_j.push_back(j2); ind_k.push_back(k2);
+  ind_i.push_back(i3); ind_j.push_back(j3); ind_k.push_back(k3);
+  ind_i.push_back(i4); ind_j.push_back(j4); ind_k.push_back(k4);  
+  
+  added += 4;
+  
+  // edge points
+  if (order > 1) {
+    // edge 1
+    for (int v = 1; v < order; v++) {
+      ind_i.push_back(i1+v*(i2-i1)/order); 
+      ind_j.push_back(j1+v*(j2-j1)/order); 
+      ind_k.push_back(k1+v*(k2-k1)/order);
+      added++;
+    }
+
+    // edge 2
+    for (int v = 1; v < order; v++) {
+      ind_i.push_back(i2+v*(i3-i2)/order); 
+      ind_j.push_back(j2+v*(j3-j2)/order); 
+      ind_k.push_back(k2+v*(k3-k2)/order);
+      added++;
+    }
+
+    // edge 3
+    for (int v = 1; v < order; v++) {
+      ind_i.push_back(i3+v*(i4-i3)/order); 
+      ind_j.push_back(j3+v*(j4-j3)/order); 
+      ind_k.push_back(k3+v*(k4-k3)/order);
+      added++;
+    }
+
+    // edge 4
+    for (int v = 1; v < order; v++) {
+      ind_i.push_back(i4+v*(i1-i4)/order); 
+      ind_j.push_back(j4+v*(j1-j4)/order); 
+      ind_k.push_back(k4+v*(k1-k4)/order);
+      added++;
+    }
+  
+  /*
+  int ioffset = (i3-i1)/abs(i2-i1);
+  int joffset = (j3-j1)/abs(j2-j1);
+  int koffset = (k3-k1)/abs(k2-k1);
+  */
+  added += getIndicesQuad(i1+offset[f][0][0], i2+offset[f][1][0], i3+offset[f][2][0], i4+offset[f][3][0],
+			  j1+offset[f][0][1], j2+offset[f][1][1], j3+offset[f][2][1], j4+offset[f][3][1],
+			  k1+offset[f][0][2], k2+offset[f][1][2], k3+offset[f][2][2], k4+offset[f][3][2],
+			  ind_i, ind_j, ind_k, order-2, f);
+  /**/
+  }
+  return added;
+}
+
 static int getIndicesFace(int i1, int i2, int i3, int i4, int j1, int j2, int j3, int j4, int k1, int k2, int k3, int k4, std::vector<int>& ind_i, std::vector<int>& ind_j, std::vector<int>& ind_k, int order, int f) {
 
   static const int offset[6][4][3] = {
@@ -350,7 +427,6 @@ static int getIndicesFace(int i1, int i2, int i3, int i4, int j1, int j2, int j3
 			  ind_i, ind_j, ind_k, order-2, f);
   /**/
   return added;
-
 }
 
 static void getIndices(int i, int j, int k, std::vector<int>& ind_i, std::vector<int>& ind_j, std::vector<int>& ind_k, int order, int startpoint=0) {
@@ -556,6 +632,12 @@ int GModel::readCGNS(const std::string &name)
     order = 1;
   }
 
+  // for entity numbering
+  int elementary_region = getNumRegions();
+  int elementary_face = getNumFaces();
+  int elementary_edge = getNumEdges();
+  int elementary_vertex = getNumVertices();
+
   // Read the zones
   for (int index_zone = 1; index_zone <= nZones; index_zone++) {
     Msg::Debug("Reading zone %i.", index_zone);
@@ -653,16 +735,25 @@ int GModel::readCGNS(const std::string &name)
     // Creating elements
     int num = 1;
 
-    int type = 5;
-    if (order == 2)
-      type = 12;
-    else if (order == 4)
-      type = 93;
+    int type_hex = 5;
+    int type_quad = 3;
+    int type_line = 1;
+    int type_pnt = 15;
+    if (order == 2) {
+      type_hex = 12;
+      type_line = 8;
+      type_quad = 10;
+    }
+    else if (order == 4){
+      type_hex = 93;
+      type_line = 27;
+      type_quad = 37;
+    }
     //else if (order == 8)
     //  type = 97;
 
     int num_elements = 0;
-    int elementary = index_zone;
+    elementary_region ++;
     int partition = 0;
     for (int i = 0; i < zoneSizes[3]; i+=order) {
       for (int j = 0; j < zoneSizes[4]; j+=order) {
@@ -675,15 +766,185 @@ int GModel::readCGNS(const std::string &name)
 	  for (int v = 0; v < ind_i.size(); v++) {
 	    vertices.push_back(vertexMap[offset+to1D(ind_i[v], ind_j[v], ind_k[v],   irmax[0], irmax[1], irmax[2])]);
 	  }
-	  MElement* e = createElementMSH(this, num, type, elementary,
+	  MElement* e = createElementMSH(this, num, type_hex, elementary_region,
 					 partition, vertices, elements);
 	  num_elements++;
 	  num++;
 	}
       }
     }
+    
+    // Create surface mesh
+    std::map<int, std::vector<int*> > forbidden;
+
+    int nconnectivity;
+    cg_n1to1(index_file, index_base, index_zone, &nconnectivity);
+    Msg::Debug("Found %i connectivity zones.", nconnectivity);
+    for (int index_section = 1; index_section <= nconnectivity; index_section++) {
+      char ConnectionName[30];
+      char DonorName[30];
+      cgsize_t range[6];
+      cgsize_t donor_range[6];
+      int transform[3];
+      cg_1to1_read(index_file, index_base, index_zone,index_section,
+		   ConnectionName, DonorName, range, donor_range, transform);
+      // Checking on which face it is
+      int face = 0;
+      if (range[0] == range[3]) {
+	if (range[0] == 1)
+	  face = 4;
+	else
+	  face = 5;
+      } else if (range[1] == range[4]) {
+        if (range[1] == 1)
+	  face = 2;
+	else
+	  face = 3;
+      } else if (range[2] == range[5]) {
+        if (range[2] == 1)
+	  face = 0;
+	else
+	  face = 1;	
+      }
+      int* range_int = new int[6];
+      for (int r = 0; r < 6; r++)
+	range_int[r] = (int)range[r];
+
+      forbidden[face].push_back(range_int);
+    }
+
+
+    for(int face = 0; face < 6; face++) {
+      int imin, imax, jmin, jmax, kmin, kmax;
+      int igrow = order;
+      int jgrow = order;
+      int kgrow = order;
+      int move[3][4];
+      switch(face) {
+      case 0:
+       	imin = 0; imax = zoneSizes[3];
+	jmin = 0; jmax = zoneSizes[4];
+	kmin = 0; kmax = 1; kgrow = 0;
+	move[0][0] = 0; move[0][1] = 0;     move[0][2] = igrow; move[0][3] = igrow;
+	move[1][0] = 0; move[1][1] = jgrow; move[1][2] = jgrow; move[1][3] = 0;
+	move[2][0] = 0; move[2][1] = 0;     move[2][2] = 0;     move[2][3] = 0;
+	break;
+      case 1:
+	imin = 0; imax = zoneSizes[3];
+	jmin = 0; jmax = zoneSizes[4];
+	kmin = zoneSizes[2]-1; kmax = zoneSizes[2]; kgrow = 0;
+	move[0][0] = 0; move[0][1] = igrow; move[0][2] = igrow; move[0][3] = 0;
+	move[1][0] = 0; move[1][1] = 0;     move[1][2] = jgrow; move[1][3] = jgrow;
+	move[2][0] = 0; move[2][1] = 0;     move[2][2] = 0;     move[2][3] = 0;
+	break;
+      case 2:
+	imin = 0; imax = zoneSizes[3];
+	jmin = 0; jmax = 1; jgrow = 0;
+	kmin = 0; kmax = zoneSizes[5];
+	move[0][0] = 0; move[0][1] = igrow; move[0][2] = igrow; move[0][3] = 0;
+	move[1][0] = 0; move[1][1] = 0;     move[1][2] = 0; move[1][3] = 0;
+	move[2][0] = 0; move[2][1] = 0;     move[2][2] = kgrow;     move[2][3] = kgrow;
+	break;
+      case 3:
+	imin = 0; imax = zoneSizes[3];
+	jmin = zoneSizes[1]-1; jmax = zoneSizes[1]; jgrow = 0;
+	kmin = 0; kmax = zoneSizes[5];
+	move[0][0] = 0; move[0][1] = 0; move[0][2] = igrow; move[0][3] = igrow;
+	move[1][0] = 0; move[1][1] = 0;     move[1][2] = 0; move[1][3] = 0;
+	move[2][0] = 0; move[2][1] = kgrow;     move[2][2] = kgrow;     move[2][3] = 0;
+	break;
+      case 4:
+	imin = 0; imax = 1; igrow = 0;
+	jmin = 0; jmax = zoneSizes[4];
+	kmin = 0; kmax = zoneSizes[5];
+	move[0][0] = 0; move[0][1] = 0; move[0][2] = 0; move[0][3] = 0;
+	move[1][0] = 0; move[1][1] = 0; move[1][2] = jgrow; move[1][3] = jgrow;
+	move[2][0] = 0; move[2][1] = kgrow;     move[2][2] = kgrow;     move[2][3] = 0;
+	break;
+      case 5:
+	imin = zoneSizes[0]-1; imax = zoneSizes[0]; igrow = 0;
+	jmin = 0; jmax = zoneSizes[4];
+	kmin = 0; kmax = zoneSizes[5];
+	move[0][0] = 0; move[0][1] = 0; move[0][2] = 0; move[0][3] = 0;
+	move[1][0] = 0; move[1][1] = jgrow; move[1][2] = jgrow; move[1][3] = 0;
+	move[2][0] = 0; move[2][1] = 0;     move[2][2] = kgrow;     move[2][3] = kgrow;
+	break;
+      }
+      
+      /**/
+
+	  /*
+	if (forbidden[face][ff][3]-1 > imin)
+	  imin = forbidden[face][ff][3]-1;
+	if (forbidden[face][ff][0]-1 < imax)
+	  imax = forbidden[face][ff][0]-1;
+
+	if (forbidden[face][ff][4]-1 > jmin)
+	  jmin = forbidden[face][ff][4]-1;
+	if (forbidden[face][ff][1]-1 < jmax)
+	  jmax = forbidden[face][ff][1]-1;
+
+	if (forbidden[face][ff][5]-1 > kmin)
+	  kmin = forbidden[face][ff][5]-1;
+	if (forbidden[face][ff][2]-1 < kmax)
+	  kmax = forbidden[face][ff][2]-1;
+      }
+
+	     printf("Range : %i-> %i   %i->%i   %i->%i\n", imin, imax, jmin, jmax, kmin, kmax);
+	*/
+      GRegion* gr = getRegionByTag(elementary_region);
+      elementary_face++;
+      num = 1;
+      for (int i = imin; i < imax; i += order) {
+	for (int j = jmin; j < jmax;  j += order) {
+	  //printf("Creating surface element\n");
+	  for (int k = kmin; k < kmax; k += order) {
+	    
+	    bool ok = true;
+	    for (int ff=0; ff < forbidden[face].size(); ff++) {
+	      int* lim = forbidden[face][ff];
+	      if ((i >= fmin(lim[0], lim[3])-1 && i <= fmax(lim[0], lim[3])-2) || igrow == 0) {
+		if ((j >= fmin(lim[1], lim[4])-1 && j <= fmax(lim[1],lim[4])-2) || jgrow == 0) {
+		  if ((k >= fmin(lim[2], lim[5])-1 && k <= fmax(lim[2], lim[5])-2) || kgrow == 0) {
+		    ok = false;
+		  }
+		}
+	      }
+	    }
+	    if (!ok) continue;
+
+	    std::vector<MVertex*> vertices;
+	    std::vector<int> ind_i, ind_j, ind_k;
+	    
+	    getIndicesQuad(i+move[0][0],i+move[0][1], i+move[0][2], i+move[0][3],
+			   j+move[1][0],j+move[1][1], j+move[1][2], j+move[1][3],
+			   k+move[2][0],k+move[2][1], k+move[2][2], k+move[2][3],
+			   ind_i, ind_j, ind_k, order, face);
+
+	    for (int v = 0; v < ind_i.size(); v++) {
+	      vertices.push_back(vertexMap[offset+to1D(ind_i[v], ind_j[v], ind_k[v],   irmax[0], irmax[1], irmax[2])]);
+	    }
+	    MElement* e = createElementMSH(this, num, type_quad, elementary_face,
+					   partition, vertices, elements);
+	    num_elements++;
+	    num++;	    
+	  }
+	}
+      }
+      GFace* gf = getFaceByTag(elementary_face);
+      if (gf)
+	gf->addRegion(gr);
+
+      for (int ff = 0; ff < forbidden[face].size(); ff++) {
+	  delete[] forbidden[face][ff];
+      }
+
+     }
   }
 
+  // store the vertices in their associate
+  
+
   // 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++)
@@ -695,8 +956,8 @@ int GModel::readCGNS(const std::string &name)
   // store the vertices in their associated geometrical entity
   _storeVerticesInEntities(vertexMap);
 
-  // store the vertices in their associate
   removeDuplicateMeshVertices(1e-8);
+  //createTopologyFromMesh();
 
   if ( cg_close (index_file) ) {
     Msg::Error("Couldnt close the file !");