diff --git a/Common/Context.h b/Common/Context.h
index d1758cd94d3685744251431d64574c5810a9d480..ff17a1187a018fd39836199009e47414f931d9eb 100644
--- a/Common/Context.h
+++ b/Common/Context.h
@@ -32,7 +32,7 @@ struct contextMeshOptions {
   int lcFromPoints, lcFromCurvature, lcExtendFromBoundary;
   int dual, voronoi, drawSkinOnly, colorCarousel, labelSampling;
   int fileFormat, nbSmoothing, algo2d, algo3d, algoSubdivide;
-  int algoRecombine, recombineAll, recombine3DAll;
+  int algoRecombine, recombineAll, recombine3DAll, flexibleTransfinite;
   //-- for recombination test (amaury) --
     int doRecombinationTest, recombinationTestStart;
     int recombinationTestNoGreedyStrat, recombinationTestNewStrat;
diff --git a/Common/OpenFile.cpp b/Common/OpenFile.cpp
index 5e1ec88ffebfd295d9966578b56697400887988c..e5eba71955384e279eea5a6707cc5284dede5dd2 100644
--- a/Common/OpenFile.cpp
+++ b/Common/OpenFile.cpp
@@ -364,10 +364,15 @@ int MergeFile(const std::string &fileName, bool warnIfMissing)
     if(status > 1) status = PView::readMED(fileName);
 #endif
   }
-  else if(ext == ".bdf" || ext == ".BDF" || ext == ".nas" || ext == ".NAS" ||
-          ext == ".dat" || ext == ".DAT"){
+  else if(ext == ".bdf" || ext == ".BDF" || ext == ".nas" || ext == ".NAS"){
     status = GModel::current()->readBDF(fileName);
   }
+  else if(ext == ".dat" || ext == ".DAT"){
+    if(!strncmp(header, "BEGIN ACTRAN", 12))
+      status = GModel::current()->readACTRAN(fileName);
+    else
+      status = GModel::current()->readBDF(fileName);
+  }
   else if(ext == ".p3d" || ext == ".P3D"){
     status = GModel::current()->readP3D(fileName);
   }
diff --git a/Geo/CMakeLists.txt b/Geo/CMakeLists.txt
index 2f9474c13ccfb8540a50b3492025bdb9360cfb88..c9cea87f405625c90835efcaea180464265087a3 100644
--- a/Geo/CMakeLists.txt
+++ b/Geo/CMakeLists.txt
@@ -27,6 +27,7 @@ set(SRC
       GModelIO_PLY.cpp GModelIO_VRML.cpp GModelIO_UNV.cpp GModelIO_BDF.cpp 
       GModelIO_IR3.cpp GModelIO_DIFF.cpp GModelIO_GEOM.cpp GModelIO_INP.cpp
       GModelIO_MAIL.cpp GModelIO_P3D.cpp GModelIO_SGEOM.cpp GModelIO_CELUM.cpp
+      GModelIO_ACTRAN.cpp
   ExtrudeParams.cpp
   Geo.cpp
   GeoStringInterface.cpp GeoInterpolation.cpp
diff --git a/Geo/GModel.h b/Geo/GModel.h
index c21bc530ea1822d2143eb7cba86c59fb2f9a9c77..001a5913f7130572c6819450d8ba1e90f33750a1 100644
--- a/Geo/GModel.h
+++ b/Geo/GModel.h
@@ -662,6 +662,9 @@ class GModel
   int writeBDF(const std::string &name, int format=0, int elementTagType=1,
                bool saveAll=false, double scalingFactor=1.0);
 
+  // Actran mesh
+  int readACTRAN(const std::string &name);
+
   // Plot3D structured mesh format
   int readP3D(const std::string &name);
   int writeP3D(const std::string &name,
diff --git a/Geo/GModelIO_ACTRAN.cpp b/Geo/GModelIO_ACTRAN.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1cad484c1af2627bf11caca4e585bf5be07f3ecb
--- /dev/null
+++ b/Geo/GModelIO_ACTRAN.cpp
@@ -0,0 +1,118 @@
+// Gmsh - Copyright (C) 1997-2013 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to the public mailing list <gmsh@geuz.org>.
+
+#include <stdlib.h>
+#include <string.h>
+#include "GModel.h"
+#include "OS.h"
+#include "MLine.h"
+#include "MTriangle.h"
+#include "MQuadrangle.h"
+#include "MTetrahedron.h"
+#include "MHexahedron.h"
+#include "Context.h"
+
+static bool getVertices(GModel *m, int num, int *n, std::vector<MVertex*> &vec)
+{
+  for(int i = 0; i < num; i++){
+    MVertex *v = m->getMeshVertexByTag(n[i]);
+    if(!v){
+      Msg::Error("Wrong vertex number %d", n[i]);
+      return false;
+    }
+    else
+      vec.push_back(v);
+  }
+  return true;
+}
+
+int GModel::readACTRAN(const std::string &name)
+{
+  FILE *fp = Fopen(name.c_str(), "r");
+  if(!fp){
+    Msg::Error("Unable to open file '%s'", name.c_str());
+    return 0;
+  }
+
+  char buffer[256];
+  if(!fgets(buffer, sizeof(buffer), fp)){ fclose(fp); return 0; }
+
+  if(strncmp(buffer, "BEGIN ACTRAN", 12)){
+    Msg::Error("Did not find ACTRAN header");
+    fclose(fp); return 0;
+  }
+
+  _vertexMapCache.clear();
+  std::map<int, std::vector<MElement*> > elements[3];
+  int nbv = 0, nbe = 0, dim = 0;
+
+  while(!feof(fp)) {
+    if(!fgets(buffer, 256, fp)) break;
+    char str[256], str2[256];
+    sscanf(buffer, "%s %s", str, str2);
+    if(!strcmp(str, "BEGIN") && !strcmp(str2, "MESH")){
+      if(!fgets(buffer, sizeof(buffer), fp)) break;
+      sscanf(buffer, "%d %d %d", &nbv, &nbe, &dim);
+      if(dim == 3 || dim == 2)
+        Msg::Info("ACTRAN mesh dimension %d", dim);
+      else{
+        Msg::Error("Cannot read ACTRAN mesh of dimension %d", dim);
+        break;
+      }
+    }
+    else if(!strcmp(str, "BEGIN") && !strcmp(str2, "NODE")){
+      Msg::Info("%d vertices", nbv);
+      for(int i = 0; i < nbv; i++) {
+        if(!fgets(buffer, sizeof(buffer), fp)) break;
+        int num;
+        double x, y, z = 0.;
+        if(dim == 3)
+          sscanf(buffer, "%d %lf %lf %lf", &num, &x, &y, &z);
+        else
+          sscanf(buffer, "%d %lf %lf", &num, &x, &y);
+        _vertexMapCache[num] = new MVertex(x, y, z, 0, num);
+      }
+    }
+    else if(!strcmp(str, "BEGIN") && !strcmp(str2, "ELEMENT")){
+      Msg::Info("%d elements", nbe);
+      for(int i = 0; i < nbe; i++) {
+        if(!fgets(buffer, sizeof(buffer), fp)) break;
+        int num, type, reg, n[8];
+        sscanf(buffer, "%d %d %d", &num, &type, &reg);
+        std::vector<MVertex*> vertices;
+        if(type == 2){
+          sscanf(buffer, "%d %d %d %d %d", &num, &type, &reg,
+                 &n[0], &n[1]);
+          if(!getVertices(this, 2, n, vertices)) break;
+          elements[0][reg].push_back(new MLine(vertices, num));
+        }
+        else if(type == 4){
+          sscanf(buffer, "%d %d %d %d %d %d", &num, &type, &reg,
+                 &n[0], &n[1], &n[2]);
+          if(!getVertices(this, 3, n, vertices)) break;
+          elements[0][reg].push_back(new MTriangle(vertices, num));
+        }
+        else if(type == 8){
+          sscanf(buffer, "%d %d %d %d %d %d %d", &num, &type, &reg,
+                 &n[0], &n[1], &n[2], &n[3]);
+          if(!getVertices(this, 4, n, vertices)) break;
+          elements[1][reg].push_back(new MTetrahedron(vertices, num));
+        }
+        else{
+          Msg::Error("Unknown type %d for element %d", type, num);
+        }
+      }
+    }
+  }
+
+  for(int i = 0; i < (int)(sizeof(elements) / sizeof(elements[0])); i++)
+    _storeElementsInEntities(elements[i]);
+  _associateEntityWithMeshVertices();
+  _storeVerticesInEntities(_vertexMapCache);
+
+  fclose(fp);
+  return 1;
+}
+