diff --git a/Common/GmshDefines.h b/Common/GmshDefines.h
index f705b484185a954f6420595fe80a8eefda8e8858..41f7f4bc05dbdcc90f28ec14e43b78ccfcf9b5ea 100644
--- a/Common/GmshDefines.h
+++ b/Common/GmshDefines.h
@@ -28,6 +28,7 @@
 #define FORMAT_P3D           28
 #define FORMAT_SVG           29
 #define FORMAT_MESH          30
+#define FORMAT_BDF           31
 
 // Element types in .msh file format
 #define LGN1 1
diff --git a/Fltk/Callbacks.cpp b/Fltk/Callbacks.cpp
index e53f049d68ed33a212ca869972df93f48c2b67ff..64f91c91d0bb70ea00f27408428fd849e3f0cddd 100644
--- a/Fltk/Callbacks.cpp
+++ b/Fltk/Callbacks.cpp
@@ -1,4 +1,4 @@
-// $Id: Callbacks.cpp,v 1.457 2006-08-31 14:15:29 geuzaine Exp $
+// $Id: Callbacks.cpp,v 1.458 2006-08-31 21:29:18 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -608,8 +608,9 @@ static char *file_types =
   "\tGmsh geometry (*.geo)"
   "\tGmsh mesh (*.msh)"
   "\tGmsh post-processing (*.pos)"
+  "\tMedit mesh (*.mesh)"
+  "\tNastran bulk data file (*.bdf)"
   "\tSTL surface mesh (*.stl)"
-  "\tMEDIT mesh (*.mesh)"
   "\tJPEG (*.jpg)"
   "\tPNG (*.png)"
   "\tBMP (*.bmp)"
@@ -676,6 +677,12 @@ int _save_mesh(char *name)
   return 1;
 }
 
+int _save_bdf(char *name)
+{
+  CreateOutputFile(name, FORMAT_BDF);
+  return 1;
+}
+
 int _save_vrml(char *name)
 {
   CreateOutputFile(name, FORMAT_VRML);
@@ -776,8 +783,9 @@ void file_save_as_cb(CALLBACK_ARGS)
     {"Gmsh options (*.opt)", _save_options},
     {"Gmsh unrolled geometry (*.geo)", _save_geo},
     {"  ", _save_auto},
-    {"I-DEAS universal mesh (*.unv)", _save_unv},
-    {"MEDIT mesh (*.mesh)", _save_mesh},
+    {"I-deas universal mesh (*.unv)", _save_unv},
+    {"Medit mesh (*.mesh)", _save_mesh},
+    {"Nastran bulk data file (*.bdf)", _save_bdf},
     {"STL surface mesh (*.stl)", _save_stl},
     {"VRML surface mesh (*.wrl)", _save_vrml},
     {"   ", _save_auto},
diff --git a/Geo/GModel.h b/Geo/GModel.h
index b8043c01fa80c159572a8757a3b9caf8c9a036df..3577a6b462f0e5c7f75aedee0947e9bf432d400e 100644
--- a/Geo/GModel.h
+++ b/Geo/GModel.h
@@ -116,19 +116,33 @@ class GModel
   // deletes all the partitions
   virtual void deleteMeshPartitions();
 
-  // IO routines
+  // IO for native Gmsh mesh file format
   int readMSH(const std::string &name);
   int writeMSH(const std::string &name, double version=1.0, bool binary=false,
 	       bool saveAll=false, double scalingFactor=1.0);
+
+  // IO for mesh statistics (as Gmsh post-processing views)
   int writePOS(const std::string &name, double scalingFactor=1.0);
+
+  // IO for stereo lithography format
   int readSTL(const std::string &name, double tolerance=1.e-3);
   int writeSTL(const std::string &name, bool binary=false, double scalingFactor=1.0);
+
+  // IO for Inventor/VRML format
   int readVRML(const std::string &name);
   int writeVRML(const std::string &name, double scalingFactor=1.0);
+
+  // IO for I-deas universal mesh format
   int writeUNV(const std::string &name, double scalingFactor=1.0);
+
+  // IO for Medit (INRIA) mesh format
   int readMESH(const std::string &name);
   int writeMESH(const std::string &name, double scalingFactor=1.0);
 
+  // IO for Nastran Bulk Data File format
+  int readBDF(const std::string &name);
+  int writeBDF(const std::string &name, double scalingFactor=1.0);
+
   // FIXME: this will be removed (and rewritten)
   smooth_normals *normals;
 };
diff --git a/Geo/GModelIO.cpp b/Geo/GModelIO.cpp
index 5b0744cbfa89a40b661b44cf1b443520c23b71fb..dd3ae6c0dba4889c656356540c8d81ed1f0e8491 100644
--- a/Geo/GModelIO.cpp
+++ b/Geo/GModelIO.cpp
@@ -1,4 +1,4 @@
-// $Id: GModelIO.cpp,v 1.31 2006-08-31 14:15:29 geuzaine Exp $
+// $Id: GModelIO.cpp,v 1.32 2006-08-31 21:29:18 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -1136,7 +1136,7 @@ int GModel::writeUNV(const std::string &name, double scalingFactor)
 
   renumberMeshVertices();
 
-  // IDEAS NODES record
+  // Nodes
   fprintf(fp, "%6d\n", -1);
   fprintf(fp, "%6d\n", 2411);
   for(viter it = firstVertex(); it != lastVertex(); ++it)
@@ -1153,7 +1153,7 @@ int GModel::writeUNV(const std::string &name, double scalingFactor)
       (*it)->mesh_vertices[i]->writeUNV(fp, scalingFactor);
   fprintf(fp, "%6d\n", -1);  
 
-  // IDEAS ELEMENTS record
+  // Elements
   fprintf(fp, "%6d\n", -1);
   fprintf(fp, "%6d\n", 2412);
   for(eiter it = firstEdge(); it != lastEdge(); ++it){
@@ -1182,7 +1182,7 @@ int GModel::writeUNV(const std::string &name, double scalingFactor)
   for(int dim = 0; dim < 4; dim++){
     std::map<int, std::vector<GEntity*> >::const_iterator it = physicals[dim].begin();
     for(; it != physicals[dim].end(); ++it){
-      // IDEAS GROUPOFNODES record
+      // Group of nodes
       fprintf(fp, "%6d\n", -1);
       fprintf(fp, "%6d\n", 790);
       fprintf(fp, "%10d%10d\n", it->first, 1);
@@ -1237,12 +1237,12 @@ int GModel::readMESH(const std::string &name)
   sscanf(buffer, "%s %d", str, &format);
 
   if(format != 1){
-    Msg(GERROR, "Non-ASCII MEDIT mesh import is not yet available");
+    Msg(GERROR, "Medit mesh import only available for ASCII files");
     return 0;
   }
 
   std::map<int, MVertex*> vertices;
-  std::map<int, std::vector<MElement*> > elements[2];
+  std::map<int, std::vector<MElement*> > elements[3];
 
   while(!feof(fp)) {
     if(!fgets(buffer, sizeof(buffer), fp)) break;
@@ -1290,6 +1290,19 @@ int GModel::readMESH(const std::string &name)
 	    (new MQuadrangle(vertices[n1], vertices[n2], vertices[n3], vertices[n4]));
 	}
       }
+      else if(!strcmp(str, "Tetrahedra")) {
+	if(!fgets(buffer, sizeof(buffer), fp)) break;
+	int nbt;
+	sscanf(buffer, "%d", &nbt);
+	Msg(INFO, "%d tetrahedra", nbt);
+	for(int i = 0; i < nbt; i++) {
+	  if(!fgets(buffer, sizeof(buffer), fp)) break;
+	  int n1, n2, n3, n4, cl;
+	  sscanf(buffer, "%d %d %d %d %d", &n1, &n2, &n3, &n4, &cl);
+	  elements[2][cl].push_back
+	    (new MTetrahedron(vertices[n1], vertices[n2], vertices[n3], vertices[n4]));
+	}
+      }
     }
   }
 
@@ -1335,11 +1348,14 @@ int GModel::writeMESH(const std::string &name, double scalingFactor)
     for(unsigned int i = 0; i < (*it)->mesh_vertices.size(); i++) 
       (*it)->mesh_vertices[i]->writeMESH(fp, scalingFactor);
   
-  int numTriangles = 0, numQuadrangles = 0;
+  int numTriangles = 0, numQuadrangles = 0, numTetrahedra = 0;
   for(fiter it = firstFace(); it != lastFace(); ++it){
     numTriangles += (*it)->triangles.size();
     numQuadrangles += (*it)->quadrangles.size();
   }
+  for(riter it = firstRegion(); it != lastRegion(); ++it){
+    numTetrahedra += (*it)->tetrahedra.size();
+  }
   if(numTriangles){
     fprintf(fp, " Triangles\n");
     fprintf(fp, " %d\n", numTriangles);
@@ -1354,9 +1370,173 @@ int GModel::writeMESH(const std::string &name, double scalingFactor)
       for(unsigned int i = 0; i < (*it)->triangles.size(); i++)
 	(*it)->quadrangles[i]->writeMESH(fp, (*it)->tag());
   }
+  if(numTetrahedra){
+    fprintf(fp, " Tetrahedra\n");
+    fprintf(fp, " %d\n", numTetrahedra);
+    for(riter it = firstRegion(); it != lastRegion(); ++it)
+      for(unsigned int i = 0; i < (*it)->tetrahedra.size(); i++)
+	(*it)->tetrahedra[i]->writeMESH(fp, (*it)->tag());
+  }
 
   fprintf(fp, " End\n");
   
   fclose(fp);
   return 1;
 }
+
+static int readElementBDF(FILE *fp, char *buffer, unsigned int numNodes, 
+			  int *num, int *region, int *nodes)
+{
+  int newline = 0; 
+  std::vector<char*> vals;
+
+  for(unsigned int i = 0; i < strlen(buffer); i++){
+    if(buffer[i] == ',') vals.push_back(&buffer[i + 1]);
+    else if(buffer[i] == '+'){ // the data continues on the next line
+      vals.pop_back();
+      newline = 1;
+      break;
+    }
+  }
+  
+  if(newline){
+    char buffer2[256];
+    if(!fgets(buffer2, sizeof(buffer2), fp)) return 0;
+    for(unsigned int i = 0; i < strlen(buffer2); i++){
+      if(buffer2[i] == ',') vals.push_back(&buffer2[i + 1]);
+    }
+  }
+  
+  if(vals.size() != numNodes + 2){
+    Msg(GERROR, "Wrong number of nodes %d for element", vals.size() - 2);
+    return 0;
+  }
+  
+  sscanf(vals[0], "%d", num);
+  sscanf(vals[1], "%d", region);
+  for(unsigned int i = 0; i < numNodes; i++)
+    if(!sscanf(vals[i + 2], "%d", &nodes[i])) return 0;
+  return 1;
+}
+
+int GModel::readBDF(const std::string &name)
+{
+  FILE *fp = fopen(name.c_str(), "r");
+  if(!fp){
+    Msg(GERROR, "Unable to open file '%s'", name.c_str());
+    return 0;
+  }
+
+  char buffer[256];
+  int num, dummy, region, n[30];
+  double x, y, z;
+
+  std::map<int, MVertex*> vertices;
+  std::map<int, std::vector<MElement*> > elements[5];
+
+  while(!feof(fp)) {
+    if(!fgets(buffer, sizeof(buffer), fp)) break;
+    if(!strncmp(buffer, "GRID", 4)){
+      sscanf(&buffer[5], "%d , %d , %lf, %lf , %lf", &num, &dummy, &x, &y, &z);
+      vertices[num] = new MVertex(x, y, z);
+    }
+    else if(!strncmp(buffer, "CTRIA3", 6)){
+      if(readElementBDF(fp, &buffer[6], 3, &num, &region, n))
+	elements[0][region].push_back
+	  (new MTriangle(vertices[n[0]], vertices[n[1]], vertices[n[2]], num));
+    }
+    else if(!strncmp(buffer, "CTRIA6", 6)){
+      if(readElementBDF(fp, &buffer[6], 6, &num, &region, n))
+	elements[0][region].push_back
+	  (new MTriangle2(vertices[n[0]], vertices[n[1]], vertices[n[2]], 
+			  vertices[n[3]], vertices[n[4]], vertices[n[5]], num));
+    }
+    else if(!strncmp(buffer, "CQUAD4", 6)){
+      if(readElementBDF(fp, &buffer[6], 4, &num, &region, n))
+	elements[1][region].push_back
+	  (new MQuadrangle(vertices[n[0]], vertices[n[1]], vertices[n[2]], 
+			   vertices[n[3]], num));
+    }
+    else if(!strncmp(buffer, "CTETRA", 6)){
+      if(readElementBDF(fp, &buffer[6], 4, &num, &region, n))
+	elements[2][region].push_back
+	  (new MTetrahedron(vertices[n[0]], vertices[n[1]], vertices[n[2]], 
+			    vertices[n[3]], num));
+    }
+    else if(!strncmp(buffer, "CHEXA", 5)){
+      if(readElementBDF(fp, &buffer[5], 8, &num, &region, n))
+	elements[3][region].push_back
+	  (new MHexahedron(vertices[n[0]], vertices[n[1]], vertices[n[2]], 
+			   vertices[n[3]], vertices[n[4]], vertices[n[5]], 
+			   vertices[n[6]], vertices[n[7]], num));
+    }
+    else if(!strncmp(buffer, "CPENTA", 6)){
+      if(readElementBDF(fp, &buffer[6], 6, &num, &region, n))
+	elements[4][region].push_back
+	  (new MPrism(vertices[n[0]], vertices[n[1]], vertices[n[2]], 
+		      vertices[n[3]], vertices[n[4]], vertices[n[5]], num));
+    }
+  }
+  
+  // store the elements in their associated elementary entity. If the
+  // entity does not exist, create a new one.
+  for(int i = 0; i < 5; i++) storeElementsInEntities(this, elements[i]);
+
+  // associate the correct geometrical entity with each mesh vertex
+  associateEntityWithVertices(this);
+
+  // store the vertices in their associated geometrical entity
+  storeVerticesInEntities(vertices);
+
+  fclose(fp);
+  return 1;
+}
+
+int GModel::writeBDF(const std::string &name, double scalingFactor)
+{
+  FILE *fp = fopen(name.c_str(), "w");
+  if(!fp){
+    Msg(GERROR, "Unable to open file '%s'", name.c_str());
+    return 0;
+  }
+
+  renumberMeshVertices();
+
+  // no idea if this header is necessary (or even what it means :-)
+  fprintf(fp, "$\n");
+  fprintf(fp, "MAT4,1,0.00000\n");
+  fprintf(fp, "PSOLID,1,1\n");
+
+  for(viter it = firstVertex(); it != lastVertex(); ++it)
+    for(unsigned int i = 0; i < (*it)->mesh_vertices.size(); i++) 
+      (*it)->mesh_vertices[i]->writeBDF(fp, scalingFactor);
+  for(eiter it = firstEdge(); it != lastEdge(); ++it)
+    for(unsigned int i = 0; i < (*it)->mesh_vertices.size(); i++)
+      (*it)->mesh_vertices[i]->writeBDF(fp, scalingFactor);
+  for(fiter it = firstFace(); it != lastFace(); ++it)
+    for(unsigned int i = 0; i < (*it)->mesh_vertices.size(); i++) 
+      (*it)->mesh_vertices[i]->writeBDF(fp, scalingFactor);
+  for(riter it = firstRegion(); it != lastRegion(); ++it)
+    for(unsigned int i = 0; i < (*it)->mesh_vertices.size(); i++) 
+      (*it)->mesh_vertices[i]->writeBDF(fp, scalingFactor);
+  
+  for(fiter it = firstFace(); it != lastFace(); ++it){
+    for(unsigned int i = 0; i < (*it)->triangles.size(); i++)
+      (*it)->triangles[i]->writeBDF(fp, (*it)->tag());
+    for(unsigned int i = 0; i < (*it)->quadrangles.size(); i++)
+      (*it)->quadrangles[i]->writeBDF(fp, (*it)->tag());
+  }
+  for(riter it = firstRegion(); it != lastRegion(); ++it){
+    for(unsigned int i = 0; i < (*it)->tetrahedra.size(); i++)
+      (*it)->tetrahedra[i]->writeBDF(fp, (*it)->tag());
+    for(unsigned int i = 0; i < (*it)->hexahedra.size(); i++)
+      (*it)->hexahedra[i]->writeBDF(fp, (*it)->tag());
+    for(unsigned int i = 0; i < (*it)->prisms.size(); i++)
+      (*it)->prisms[i]->writeBDF(fp, (*it)->tag());
+  }
+  
+  fprintf(fp, "ENDDATA\n");
+   
+  fclose(fp);
+  return 1;
+}
diff --git a/Geo/MElement.cpp b/Geo/MElement.cpp
index 1b0bc6ea6f8d20cd0b6dfe773ecd5d54166bde99..74cc6f72065ba56273228050a97da9c180291eb9 100644
--- a/Geo/MElement.cpp
+++ b/Geo/MElement.cpp
@@ -1,4 +1,4 @@
-// $Id: MElement.cpp,v 1.11 2006-08-29 21:19:34 geuzaine Exp $
+// $Id: MElement.cpp,v 1.12 2006-08-31 21:29:18 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -278,3 +278,14 @@ void MElement::writeMESH(FILE *fp, int elementary)
     fprintf(fp, " %d", getVertex(i)->getNum());
   fprintf(fp, " %d\n", elementary);
 }
+
+void MElement::writeBDF(FILE *fp, int elementary)
+{
+  char *str = getStringForBDF();
+  if(str){
+    fprintf(fp, "%s,%d,%d", str, _num, elementary);
+    for(int i = 0; i < getNumVertices(); i++)
+      fprintf(fp, ",%d", getVertex(i)->getNum());
+    fprintf(fp, "\n");
+  }
+}
diff --git a/Geo/MElement.h b/Geo/MElement.h
index 9fb1c068e7f77e10eb2fabe9b81d09f1d0e69a68..d42e1a58ed40c09c2cf4cd1e6bbfcdc868315a48 100644
--- a/Geo/MElement.h
+++ b/Geo/MElement.h
@@ -138,9 +138,11 @@ class MElement
   virtual void writeVRML(FILE *fp);
   virtual void writeUNV(FILE *fp, int elementary);
   virtual void writeMESH(FILE *fp, int elementary);
-  virtual char *getStringForPOS() = 0;
+  virtual void writeBDF(FILE *fp, int elementary);
   virtual int getTypeForMSH() = 0;
   virtual int getTypeForUNV() = 0;
+  virtual char *getStringForPOS() = 0;
+  virtual char *getStringForBDF() = 0;
 };
 
 class MLine : public MElement {
@@ -168,6 +170,7 @@ class MLine : public MElement {
   int getTypeForMSH(){ return LGN1; }
   int getTypeForUNV(){ return 21; } // BEAM
   char *getStringForPOS(){ return "SL"; }
+  char *getStringForBDF(){ return 0; }
 };
 
 class MLine2 : public MLine {
@@ -202,6 +205,7 @@ class MLine2 : public MLine {
   int getTypeForMSH(){ return LGN2; }
   int getTypeForUNV(){ return 24; } // BEAM2
   char *getStringForPOS(){ return "SL2"; }
+  char *getStringForBDF(){ return 0; }
 };
 
 class MTriangle : public MElement {
@@ -235,6 +239,7 @@ class MTriangle : public MElement {
   int getTypeForMSH(){ return TRI1; }
   int getTypeForUNV(){ return 91; } // THINSHLL
   char *getStringForPOS(){ return "ST"; }
+  char *getStringForBDF(){ return "CTRIA3"; }
 };
 
 class MTriangle2 : public MTriangle {
@@ -288,6 +293,7 @@ class MTriangle2 : public MTriangle {
   int getTypeForMSH(){ return TRI2; }
   int getTypeForUNV(){ return 92; } // THINSHLL2
   char *getStringForPOS(){ return "ST2"; }
+  char *getStringForBDF(){ return "CTRIA6"; }
 };
 
 class MQuadrangle : public MElement {
@@ -318,6 +324,7 @@ class MQuadrangle : public MElement {
   int getTypeForMSH(){ return QUA1; }
   int getTypeForUNV(){ return 94; } // QUAD
   char *getStringForPOS(){ return "SQ"; }
+  char *getStringForBDF(){ return "CQUAD4"; }
 };
 
 class MQuadrangle2 : public MQuadrangle {
@@ -345,6 +352,7 @@ class MQuadrangle2 : public MQuadrangle {
   int getTypeForMSH(){ return QUA2; }
   int getTypeForUNV(){ return 95; } // ???? QUAD2
   char *getStringForPOS(){ return "SQ2"; }
+  char *getStringForBDF(){ return 0; }
 };
 
 class MTetrahedron : public MElement {
@@ -380,6 +388,7 @@ class MTetrahedron : public MElement {
   int getTypeForMSH(){ return TET1; }
   int getTypeForUNV(){ return 111; } // SOLIDFEM
   char *getStringForPOS(){ return "SS"; }
+  char *getStringForBDF(){ return "CTETRA"; }
   virtual double getVolume()
   { 
     double mat[3][3];
@@ -431,6 +440,7 @@ class MTetrahedron2 : public MTetrahedron {
   int getTypeForMSH(){ return TET2; }
   int getTypeForUNV(){ return 118; } // SOLIDFEM2
   char *getStringForPOS(){ return "SS2"; }
+  char *getStringForBDF(){ return 0; }
   void setVolumePositive()
   {
     if(getVolumeSign() < 0){
@@ -478,6 +488,7 @@ class MHexahedron : public MElement {
   int getTypeForMSH(){ return HEX1; }
   int getTypeForUNV(){ return 115; } // BRICK
   char *getStringForPOS(){ return "SH"; }
+  char *getStringForBDF(){ return "CHEXA"; }
   virtual int getVolumeSign()
   { 
     double mat[3][3];
@@ -535,6 +546,7 @@ class MHexahedron2 : public MHexahedron {
   int getTypeForMSH(){ return HEX2; }
   int getTypeForUNV(){ return 116; } // ???? BRICK2
   char *getStringForPOS(){ return "SH2"; }
+  char *getStringForBDF(){ return 0; }
   void setVolumePositive()
   {
     if(getVolumeSign() < 0){
@@ -592,6 +604,7 @@ class MPrism : public MElement {
   int getTypeForMSH(){ return PRI1; }
   int getTypeForUNV(){ return 112; } // WEDGE
   char *getStringForPOS(){ return "SI"; }
+  char *getStringForBDF(){ return "CPENTA"; }
   virtual int getVolumeSign()
   { 
     double mat[3][3];
@@ -645,6 +658,7 @@ class MPrism2 : public MPrism {
   int getTypeForMSH(){ return PRI2; }
   int getTypeForUNV(){ return 113; } // ???? WEDGE2
   char *getStringForPOS(){ return "SI2"; }
+  char *getStringForBDF(){ return 0; }
   void setVolumePositive()
   {
     if(getVolumeSign() < 0){
@@ -698,6 +712,7 @@ class MPyramid : public MElement {
   int getTypeForMSH(){ return PYR1; }
   int getTypeForUNV(){ throw; }
   char *getStringForPOS(){ return "SY"; }
+  char *getStringForBDF(){ return 0; }
   virtual int getVolumeSign()
   { 
     double mat[3][3];
@@ -749,6 +764,7 @@ class MPyramid2 : public MPyramid {
   int getTypeForMSH(){ return PYR2; }
   int getTypeForUNV(){ throw; }
   char *getStringForPOS(){ return "SY2"; }
+  char *getStringForBDF(){ return 0; }
   void setVolumePositive()
   {
     if(getVolumeSign() < 0){
diff --git a/Geo/MVertex.cpp b/Geo/MVertex.cpp
index 39a4db192f44ae63b7277e776d7ffef72c076ad0..bae513d7f2ee4f83400fcb94a9c3662c32442578 100644
--- a/Geo/MVertex.cpp
+++ b/Geo/MVertex.cpp
@@ -1,4 +1,4 @@
-// $Id: MVertex.cpp,v 1.6 2006-08-19 18:48:06 geuzaine Exp $
+// $Id: MVertex.cpp,v 1.7 2006-08-31 21:29:18 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -83,3 +83,9 @@ void MVertex::writeMESH(FILE *fp, double scalingFactor)
   fprintf(fp, " %20.14E      %20.14E      %20.14E      %d\n", 
 	  x() * scalingFactor, y() * scalingFactor, z() * scalingFactor, 0);
 }
+
+void MVertex::writeBDF(FILE *fp, double scalingFactor)
+{
+  fprintf(fp, "GRID,%d,%d,%f,%f,%f\n", _num, 0,
+	  x() * scalingFactor, y() * scalingFactor, z() * scalingFactor);
+}
diff --git a/Geo/MVertex.h b/Geo/MVertex.h
index ae6d1d4c04f66e92d998ce28de9930b47ebb2098..688c8e82bb484c4d64c27b2d14d198d3677b20ee 100644
--- a/Geo/MVertex.h
+++ b/Geo/MVertex.h
@@ -83,6 +83,7 @@ class MVertex{
   void writeVRML(FILE *fp, double scalingFactor=1.0);
   void writeUNV(FILE *fp, double scalingFactor=1.0);
   void writeMESH(FILE *fp, double scalingFactor=1.0);
+  void writeBDF(FILE *fp, double scalingFactor=1.0);
 };
 
 class MEdgeVertex : public MVertex{
diff --git a/Parser/CreateFile.cpp b/Parser/CreateFile.cpp
index b0e988f8b296814fa06a7a9a5b4a7857d672cbe5..6b59d1e9fbfcdfcccb5999491ec3a30d2cb5ce79 100644
--- a/Parser/CreateFile.cpp
+++ b/Parser/CreateFile.cpp
@@ -1,4 +1,4 @@
-// $Id: CreateFile.cpp,v 1.5 2006-08-31 14:15:29 geuzaine Exp $
+// $Id: CreateFile.cpp,v 1.6 2006-08-31 21:29:18 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -60,6 +60,7 @@ int GuessFileFormatFromFileName(char *name)
   else if(!strcmp(ext, ".unv"))     return FORMAT_UNV;
   else if(!strcmp(ext, ".stl"))     return FORMAT_STL;
   else if(!strcmp(ext, ".mesh"))    return FORMAT_MESH;
+  else if(!strcmp(ext, ".bdf"))     return FORMAT_BDF;
   else if(!strcmp(ext, ".wrl"))     return FORMAT_VRML;
   else if(!strcmp(ext, ".vrml"))    return FORMAT_VRML;
   else if(!strcmp(ext, ".gif"))     return FORMAT_GIF;
@@ -88,6 +89,7 @@ void GetDefaultFileName(int format, char *name)
   case FORMAT_UNV:  strcpy(ext, ".unv"); break;
   case FORMAT_STL:  strcpy(ext, ".stl"); break;
   case FORMAT_MESH: strcpy(ext, ".mesh"); break;
+  case FORMAT_BDF:  strcpy(ext, ".bdf"); break;
   case FORMAT_VRML: strcpy(ext, ".wrl"); break;
   case FORMAT_GIF:  strcpy(ext, ".gif"); break;
   case FORMAT_JPEG: strcpy(ext, ".jpg"); break;
@@ -163,6 +165,10 @@ void CreateOutputFile(char *filename, int format)
     GMODEL->writeMESH(name, CTX.mesh.scaling_factor);
     break;
 
+  case FORMAT_BDF:
+    GMODEL->writeBDF(name, CTX.mesh.scaling_factor);
+    break;
+
   case FORMAT_POS:
     GMODEL->writePOS(name);
     break;
diff --git a/Parser/OpenFile.cpp b/Parser/OpenFile.cpp
index a649313a08242ef2df24ae365daa56945cf92eee..d66ca18aa004d80b9eb3ae509165234ed9eeb2c5 100644
--- a/Parser/OpenFile.cpp
+++ b/Parser/OpenFile.cpp
@@ -1,4 +1,4 @@
-// $Id: OpenFile.cpp,v 1.118 2006-08-26 15:13:22 remacle Exp $
+// $Id: OpenFile.cpp,v 1.119 2006-08-31 21:29:18 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -293,6 +293,9 @@ int MergeProblem(char *name, int warn_if_missing)
   else if(!strcmp(ext, ".mesh") || !strcmp(ext, ".MESH")){
     status = GMODEL->readMESH(name);
   }
+  else if(!strcmp(ext, ".bdf") || !strcmp(ext, ".BDF")){
+    status = GMODEL->readBDF(name);
+  }
 #if defined(HAVE_FLTK)
   else if(!strcmp(ext, ".pnm") || !strcmp(ext, ".PNM") ||
 	  !strcmp(ext, ".pbm") || !strcmp(ext, ".PBM") ||