diff --git a/Common/CommandLine.cpp b/Common/CommandLine.cpp
index 4c611ebc2687b6a3facff5ed84f9bb6711e0a737..19c233f24cb160fcbfcc24bc40322283a00c8005 100644
--- a/Common/CommandLine.cpp
+++ b/Common/CommandLine.cpp
@@ -74,7 +74,7 @@ std::vector<std::pair<std::string, std::string> > GetUsage()
   s.push_back(mp("-o file",            "Specify output file name"));
   s.push_back(mp("-format string",     "Select output mesh format (auto (default), msh, "
                                        "msh1, msh2, unv, vrml, ply2, stl, mesh, bdf, cgns, "
-                                       "p3d, diff, med, ...)"));
+                                       "p3d, diff, med, neu, ...)"));
   s.push_back(mp("-bin",               "Use binary format when available"));
   s.push_back(mp("-refine",            "Perform uniform mesh refinement, then exit"));
   s.push_back(mp("-reclassify",        "Reclassify mesh, then exit"));
@@ -106,7 +106,7 @@ std::vector<std::pair<std::string, std::string> > GetUsage()
   s.push_back(mp("-rand float",        "Set random perturbation factor"));
   s.push_back(mp("-bgm file",          "Load background mesh from file"));
   s.push_back(mp("-check",             "Perform various consistency checks on mesh"));
-  s.push_back(mp("-ignorePartBound",   "Ignore partition boundaries")); 
+  s.push_back(mp("-ignorePartBound",   "Ignore partition boundaries"));
   s.push_back(mp("-ignorePeriocity",   "Ignore periodic boundaries"));
   s.push_back(mp("-oneFilePerPart",    "Save mesh partitions in separate files"));
 #if defined(HAVE_FLTK)
@@ -1163,5 +1163,3 @@ void GetOptions(int argc, char *argv[])
   if(CTX::instance()->terminal == 99)
     CTX::instance()->terminal = terminal;
 }
-
-
diff --git a/Common/CreateFile.cpp b/Common/CreateFile.cpp
index 7ec744426dacf7c2091fc665bf8c63b64f8c7d16..532c68dcabf1d64ecf205a15b9bd0f4f93e63b30 100644
--- a/Common/CreateFile.cpp
+++ b/Common/CreateFile.cpp
@@ -79,6 +79,7 @@ int GetFileFormatFromExtension(const std::string &ext)
   else if(ext == ".stp")  return FORMAT_STEP;
   else if(ext == ".iges") return FORMAT_IGES;
   else if(ext == ".igs")  return FORMAT_IGES;
+  else if(ext == ".neu")  return FORMAT_NEU;
   else                           return -1;
 }
 
@@ -133,6 +134,7 @@ std::string GetDefaultFileName(int format)
   case FORMAT_BREP: name += ".brep"; break;
   case FORMAT_IGES: name += ".iges"; break;
   case FORMAT_STEP: name += ".step"; break;
+  case FORMAT_NEU: name += ".neu"; break;
   default: break;
   }
   return name;
@@ -396,6 +398,11 @@ void CreateOutputFile(const std::string &fileName, int format,
     GModel::current()->writeOCCSTEP(name);
     break;
 
+  case FORMAT_NEU:
+    GModel::current()->writeNEU
+      (name, CTX::instance()->mesh.saveAll, CTX::instance()->mesh.scalingFactor);
+    break;
+
 #if defined(HAVE_FLTK)
   case FORMAT_PPM:
   case FORMAT_YUV:
diff --git a/Common/GmshDefines.h b/Common/GmshDefines.h
index 630462e3fd90e1cf2571754bc7be9ec00270d903..770752ca4961d2d75d57aafcad89db134f538d95 100644
--- a/Common/GmshDefines.h
+++ b/Common/GmshDefines.h
@@ -7,54 +7,55 @@
 #define _GMSH_DEFINES_H_
 
 // IO file formats (numbers should not be changed)
-#define FORMAT_MSH   1
-#define FORMAT_UNV   2
-#define FORMAT_GREF  3
-#define FORMAT_XPM   4
-#define FORMAT_PS    5
-#define FORMAT_BMP   6
-#define FORMAT_GIF   7
-#define FORMAT_GEO   8
-#define FORMAT_JPEG  9
-#define FORMAT_AUTO  10
-#define FORMAT_PPM   11
-#define FORMAT_YUV   12
-#define FORMAT_DMG   13
-#define FORMAT_SMS   14
-#define FORMAT_OPT   15
-#define FORMAT_VTK   16
-#define FORMAT_MPEG  17
-#define FORMAT_TEX   18
-#define FORMAT_VRML  19
-#define FORMAT_EPS   20
-#define FORMAT_MAIL  21
-#define FORMAT_PNG   22
-#define FORMAT_TXT   23
-#define FORMAT_PDF   24
-#define FORMAT_RMED  25
-#define FORMAT_POS   26
-#define FORMAT_STL   27
-#define FORMAT_P3D   28
-#define FORMAT_SVG   29
-#define FORMAT_MESH  30
-#define FORMAT_BDF   31
-#define FORMAT_CGNS  32
-#define FORMAT_MED   33
-#define FORMAT_DIFF  34
-#define FORMAT_BREP  35
-#define FORMAT_STEP  36
-#define FORMAT_IGES  37
-#define FORMAT_IR3   38
-#define FORMAT_INP   39
-#define FORMAT_PLY2  40
-#define FORMAT_CELUM 41
-#define FORMAT_SU2   42
+#define FORMAT_MSH          1
+#define FORMAT_UNV          2
+#define FORMAT_GREF         3
+#define FORMAT_XPM          4
+#define FORMAT_PS           5
+#define FORMAT_BMP          6
+#define FORMAT_GIF          7
+#define FORMAT_GEO          8
+#define FORMAT_JPEG         9
+#define FORMAT_AUTO         10
+#define FORMAT_PPM          11
+#define FORMAT_YUV          12
+#define FORMAT_DMG          13
+#define FORMAT_SMS          14
+#define FORMAT_OPT          15
+#define FORMAT_VTK          16
+#define FORMAT_MPEG         17
+#define FORMAT_TEX          18
+#define FORMAT_VRML         19
+#define FORMAT_EPS          20
+#define FORMAT_MAIL         21
+#define FORMAT_PNG          22
+#define FORMAT_TXT          23
+#define FORMAT_PDF          24
+#define FORMAT_RMED         25
+#define FORMAT_POS          26
+#define FORMAT_STL          27
+#define FORMAT_P3D          28
+#define FORMAT_SVG          29
+#define FORMAT_MESH         30
+#define FORMAT_BDF          31
+#define FORMAT_CGNS         32
+#define FORMAT_MED          33
+#define FORMAT_DIFF         34
+#define FORMAT_BREP         35
+#define FORMAT_STEP         36
+#define FORMAT_IGES         37
+#define FORMAT_IR3          38
+#define FORMAT_INP          39
+#define FORMAT_PLY2         40
+#define FORMAT_CELUM        41
+#define FORMAT_SU2          42
 #define FORMAT_MPEG_PREVIEW 43
-#define FORMAT_PGF   44
-#define FORMAT_PVTU  45
-#define FORMAT_X3D   46
-#define FORMAT_TOCHNOG 47
-#define FORMAT_TIKZ  48
+#define FORMAT_PGF          44
+#define FORMAT_PVTU         45
+#define FORMAT_X3D          46
+#define FORMAT_TOCHNOG      47
+#define FORMAT_TIKZ         48
+#define FORMAT_NEU          49
 
 // Element types
 #define TYPE_PNT     1
diff --git a/Geo/CMakeLists.txt b/Geo/CMakeLists.txt
index 2ac9ea624b919b808d1946d9943ee9b20984b87d..e8d73035adf0db89d78b9648e7a62cee26ddba3c 100644
--- a/Geo/CMakeLists.txt
+++ b/Geo/CMakeLists.txt
@@ -15,7 +15,7 @@ set(SRC
    gmshSurface.cpp
    OCCVertex.cpp OCCEdge.cpp OCCFace.cpp OCCRegion.cpp
    GenericVertex.cpp GenericEdge.cpp GenericFace.cpp GenericRegion.cpp
-    discreteEdge.cpp discreteFace.cpp discreteDiskFace.cpp discreteRegion.cpp 
+    discreteEdge.cpp discreteFace.cpp discreteDiskFace.cpp discreteRegion.cpp
     fourierEdge.cpp fourierFace.cpp fourierProjectionFace.cpp
   ACISVertex.cpp
   ACISEdge.cpp
@@ -25,12 +25,12 @@ set(SRC
     GModelVertexArrays.cpp
     GModelFactory.cpp
     GModelIO_GEO.cpp GModelIO_ACIS.cpp GModelIO_OCC.cpp GModelIO_TOCHNOG.cpp
-      GModelIO_Fourier.cpp 
-    GModelIO_MSH.cpp GModelIO_MSH2.cpp GModelIO_VTK.cpp GModelIO_POS.cpp 
-      GModelIO_CGNS.cpp GModelIO_MED.cpp GModelIO_MESH.cpp GModelIO_STL.cpp 
-      GModelIO_PLY.cpp GModelIO_VRML.cpp GModelIO_UNV.cpp GModelIO_BDF.cpp 
+      GModelIO_Fourier.cpp
+    GModelIO_MSH.cpp GModelIO_MSH2.cpp GModelIO_VTK.cpp GModelIO_POS.cpp
+      GModelIO_CGNS.cpp GModelIO_MED.cpp GModelIO_MESH.cpp GModelIO_STL.cpp
+      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_CELUM.cpp
+      GModelIO_MAIL.cpp GModelIO_P3D.cpp GModelIO_CELUM.cpp GModelIO_NEU.cpp
       GModelIO_ACTRAN.cpp GModelIO_SU2.cpp GModelIO_SAMCEF.cpp
   ExtrudeParams.cpp
   Geo.cpp
@@ -51,5 +51,5 @@ set(SRC
   MVertexBoundaryLayerData.cpp
 )
 
-file(GLOB HDR RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.h) 
+file(GLOB HDR RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.h)
 append_gmsh_src(Geo "${SRC};${HDR}")
diff --git a/Geo/GModel.h b/Geo/GModel.h
index b37ed3715174d4a968d805eae56ba4c54b2bdd43..4f382250a7f521dbd3bcaf37079279dabe623f72 100644
--- a/Geo/GModel.h
+++ b/Geo/GModel.h
@@ -724,6 +724,9 @@ class GModel {
 
   // SU2 mesh file
   int writeSU2(const std::string &name, bool saveAll, double scalingFactor);
+
+  // GAMBIT neutral mesh file (.neu)
+  int writeNEU(const std::string &name, bool saveAll, double scalingFactor);
 };
 
 #endif
diff --git a/Geo/GModelIO_NEU.cpp b/Geo/GModelIO_NEU.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d5aa503e8e88336b09e6cb76258e666a424ef869
--- /dev/null
+++ b/Geo/GModelIO_NEU.cpp
@@ -0,0 +1,263 @@
+// Gmsh - Copyright (C) 1997-2017 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@onelab.info>.
+
+#include <algorithm>
+#include <limits>
+#include <unordered_map>
+#include "GModel.h"
+#include "OS.h"
+#include "MTriangle.h"
+#include "MTetrahedron.h"
+
+namespace
+{
+  static const auto GAMBIT_TYPE_EDGE = 1;
+  static const auto GAMBIT_TYPE_QUAD = 2;
+  static const auto GAMBIT_TYPE_TRI  = 3;
+  static const auto GAMBIT_TYPE_TET  = 6;
+
+  static const std::unordered_map<std::string, unsigned> BOUNDARY_CODES {
+    {"UNSPECIFIED", 0},
+    {"AXIS", 1},
+    {"CONJUGATE", 2},
+    {"CONVECTION", 3},
+    {"CYCLIC", 4},
+    {"DEAD", 5},
+    {"ELEMENT_SID", 6},
+    {"ESPECIES", 7},
+    {"EXHAUST_FAN", 8},
+    {"FAN", 9},
+    {"FREE_SURFACE", 10},
+    {"GAP", 11},
+    {"INFLOW", 12},
+    {"INLET", 13},
+    {"INLET_VENT", 14},
+    {"INTAKE_FAN", 15},
+    {"INTERFACE", 16},
+    {"INTERIOR", 17},
+    {"INTERNAL", 18},
+    {"LIVE", 19},
+    {"MASS_FLOW_INLET", 20},
+    {"MELT", 21},
+    {"MELT_INTERFACE", 22},
+    {"MOVING_BOUNDARY", 23},
+    {"NODE", 24},
+    {"OUTFLOW", 25},
+    {"OUTLET", 26},
+    {"OUTLET_VENT", 27},
+    {"PERIODIC", 28},
+    {"PLOT", 29},
+    {"POROUS", 30},
+    {"POROUS_JUMP", 31},
+    {"PRESSURE", 32},
+    {"PRESSURE_FAR_FIELD", 33},
+    {"PRESSURE_INFLOW", 34},
+    {"PRESSURE_INLET", 35},
+    {"PRESSURE_OUTFLOW", 36},
+    {"PRESSURE_OUTLET", 37},
+    {"RADIATION", 38},
+    {"RADIATOR", 39},
+    {"RECIRCULATION_INLET", 40},
+    {"RECIRCULATION_OUTLET", 41},
+    {"SLIP", 42},
+    {"SREACTION", 43},
+    {"SURFACE", 44},
+    {"SYMMETRY", 45},
+    {"TRACTION", 46},
+    {"TRAJECTORY", 47},
+    {"VELOCITY", 48},
+    {"VELOCITY_INLET", 49},
+    {"VENT", 50},
+    {"WALL", 51},
+    {"SIDE", 51},
+    {"SPRING", 52},
+  };
+
+  // Gambit numbers its faces slightly differently
+  static const unsigned GAMBIT_FACE_MAP[4] = {1,2,4,3};
+
+  unsigned const gambitBoundaryCode(std::string name)
+  {
+    std::transform(name.begin(), name.end(),name.begin(), ::toupper);
+    auto code = BOUNDARY_CODES.find(name);
+    return code == BOUNDARY_CODES.end() ? 0 : code->second;
+  }
+
+  typedef std::pair<unsigned, unsigned> TetFacePair;
+  typedef std::unordered_map<unsigned, std::vector<TetFacePair> > IDTetFaceMap;
+
+  bool const sortBCs(TetFacePair const& lhs, TetFacePair const& rhs)
+  {
+    return lhs.first < rhs.first;
+  }
+
+  IDTetFaceMap const gatherBC(GModel* gm)
+  {
+    // create association map for vertices and faces
+    std::unordered_map<unsigned, std::vector<unsigned> > vertmap;
+    for (auto it = gm->firstFace(); it != gm->lastFace(); ++it) {
+      for (auto const& tri: (*it)->triangles) {
+        for (auto i = 0; i < tri->getNumVertices(); ++i) {
+          vertmap[tri->getVertex(i)->getNum()].push_back(tri->getNum());
+        }
+      }
+    }
+
+    // determine which faces belong to which tetrahedra by comparing vertices
+    IDTetFaceMap tetfacemap;
+    for (auto it = gm->firstRegion(); it != gm->lastRegion(); ++it) {
+      for (auto const& tet: (*it)->tetrahedra) {
+        for (auto faceNum = 0; faceNum < tet->getNumFaces(); ++faceNum) {
+          std::vector<MVertex*> verts;
+          tet->getFaceVertices(faceNum, verts);
+
+          auto current = vertmap[verts[0]->getNum()];
+          for (unsigned j = 1; j < verts.size() && current.size() != 0; ++j) {
+            std::vector<unsigned> common_data;
+            set_intersection(current.begin(), current.end(),
+                             vertmap[verts[j]->getNum()].begin(),
+                             vertmap[verts[j]->getNum()].end(),
+                             std::back_inserter(common_data));
+            current = common_data;
+          }
+          if (current.size() == 1) {
+            tetfacemap[current[0]].push_back(
+                TetFacePair(tet->getNum(), GAMBIT_FACE_MAP[faceNum]));
+          }
+        }
+      }
+    }
+
+    // populate boundary conditions for tetrahedra given triangle physicals
+    IDTetFaceMap boundaryConditions;
+    for (auto it = gm->firstFace(); it != gm->lastFace(); ++it) {
+      if ((*it)->physicals.size()) {
+        for (auto const& phys: (*it)->physicals) {
+          for (auto const& tri: (*it)->triangles) {
+            auto tets = tetfacemap.find(tri->getNum());
+            if (tets != tetfacemap.end()) {
+              for (auto const& tet: tets->second) {
+                boundaryConditions[phys].push_back(tet);
+              }
+            }
+          }
+        }
+      }
+    }
+
+    return boundaryConditions;
+  }
+}
+
+// for a specification of the GAMBIT neutral format:
+//   http://web.stanford.edu/class/me469b/handouts/gambit_write.pdf
+int GModel::writeNEU(const std::string &name, bool saveAll,
+                     double scalingFactor)
+{
+  auto fp = Fopen(name.c_str(), "w");
+  if (!fp) {
+    Msg::Error("Unable to open file '%s'", name.c_str());
+    return 0;
+  }
+
+  // gather tetrahedra and id normalization information
+  auto numTetrahedra = 0;
+  auto lowestId = std::numeric_limits<int>::max();
+  std::unordered_map<unsigned, std::vector<unsigned> > elementGroups;
+  for (riter it = firstRegion(); it != lastRegion(); ++it) {
+    if (saveAll || (*it)->physicals.size()) {
+      numTetrahedra += (*it)->tetrahedra.size();
+
+      for (auto const& phys: (*it)->physicals) {
+        for (auto const& tet: (*it)->tetrahedra) {
+          elementGroups[phys].push_back(tet->getNum());
+
+          if (tet->getNum() < lowestId) lowestId = tet->getNum()-1;
+        }
+      }
+    }
+  }
+
+  auto boundaryConditions = gatherBC(this);
+
+  // Metadata
+  fprintf(fp, "        CONTROL INFO 2.0.0\n");
+  fprintf(fp, "** GAMBIT NEUTRAL FILE\n");
+  fprintf(fp, "Gmsh mesh in GAMBIT neutral file format\n");
+  fprintf(fp, "PROGRAM:                Gambit     VERSION:  2.0.0\n");
+
+  char datestring[256];
+  time_t rawtime;
+  struct tm* timeinfo;
+  time(&rawtime);
+  timeinfo = localtime(&rawtime);
+  strftime(datestring, sizeof(datestring), "%c", timeinfo);
+  fprintf(fp, "%s\n", datestring);
+
+  fprintf(fp, "     NUMNP     NELEM     NGRPS    NBSETS     NDFCD     NDFVL\n");
+  fprintf(fp, " %9d %9d %9lu %9lu %9d %9d\n", indexMeshVertices(saveAll), numTetrahedra,
+          elementGroups.size(), boundaryConditions.size(), getDim(),
+          getDim());
+  fprintf(fp, "ENDOFSECTION\n");
+
+  // Nodes
+  fprintf(fp, "   NODAL COORDINATES 2.0.0\n");
+  std::vector<GEntity*> entities;
+  getEntities(entities);
+  for (unsigned i = 0; i < entities.size(); ++i) {
+    for (unsigned j = 0; j < entities[i]->mesh_vertices.size(); ++j) {
+      entities[i]->mesh_vertices[j]->writeNEU(fp, getDim(), scalingFactor);
+    }
+  }
+  fprintf(fp, "ENDOFSECTION\n");
+
+  // Elements
+  fprintf(fp, "      ELEMENTS/CELLS 2.0.0\n");
+  for (riter it = firstRegion(); it != lastRegion(); ++it) {
+    auto numPhys = (*it)->physicals.size();
+    if (saveAll || numPhys) {
+      for (unsigned i = 0; i < (*it)->tetrahedra.size(); ++i) {
+        (*it)->tetrahedra[i]->writeNEU(fp, GAMBIT_TYPE_TET, lowestId,
+                                        numPhys ? (*it)->physicals[0] : 0);
+      }
+    }
+  }
+  fprintf(fp, "ENDOFSECTION\n");
+
+  // Element Groups
+  for (auto const& kv: elementGroups) {
+    fprintf(fp, "       ELEMENT GROUP 2.0.0\n");
+    fprintf(fp, "GROUP: %10d ELEMENTS: %10lu MATERIAL: 0 NFLAGS: %10d\n", kv.first, kv.second.size(), 1);
+    fprintf(fp, "Material group %d\n", kv.first);
+    fprintf(fp, "       0");
+
+    unsigned i = 0;
+    for (auto const& elem: kv.second) {
+      if (i++ % 10 == 0) {
+        fprintf(fp, "\n");
+      }
+      fprintf(fp, "%8d", elem-lowestId);
+    }
+    fprintf(fp, "\n");
+    fprintf(fp, "ENDOFSECTION\n");
+  }
+
+  // Boundary Conditions
+  for (auto &kv: boundaryConditions) {
+    fprintf(fp, "       BOUNDARY CONDITIONS 2.0.0\n");
+
+    auto regionName = getPhysicalName(2, kv.first);
+    fprintf(fp, "%32s%8d%8lu%8d%8d\n", regionName.c_str(), 1, kv.second.size(), 0, gambitBoundaryCode(regionName));
+    std::sort(kv.second.begin(), kv.second.end(), sortBCs);
+    for (auto const& boundary: kv.second) {
+      fprintf(fp, "%10d %5d %5d\n", boundary.first-lowestId, GAMBIT_TYPE_TET, boundary.second);
+    }
+
+    fprintf(fp, "ENDOFSECTION\n");
+  }
+
+  fclose(fp);
+  return 1;
+}
diff --git a/Geo/MElement.cpp b/Geo/MElement.cpp
index 05689e94f56b26f12960f6908fd4d999707f25b3..4914775dd8b4b36cbc797055e4c4ae0f1564349f 100644
--- a/Geo/MElement.cpp
+++ b/Geo/MElement.cpp
@@ -1338,6 +1338,19 @@ void MElement::writeMESH(FILE *fp, int elementTagType, int elementary,
   if(physical < 0) reverse();
 }
 
+void MElement::writeNEU(FILE *fp, unsigned gambitType, int idAdjust, int phys)
+{
+  if(phys < 0) reverse();
+
+  fprintf(fp, "%8d %2d %2d ", _num-idAdjust, gambitType, getNumVertices());
+  for(int i = 0; i < getNumVertices(); ++i) {
+    fprintf(fp, "%8d", getVertex(i)->getIndex());
+  }
+  fprintf(fp, "\n");
+
+  if(phys < 0) reverse();
+}
+
 void MElement::writeIR3(FILE *fp, int elementTagType, int num, int elementary,
                         int physical)
 {
diff --git a/Geo/MElement.h b/Geo/MElement.h
index 20b7f37ffee9b91ce44b6cb17b833d9015387537..cf86a181b4c360fc157a8623725ac20c5c056599 100644
--- a/Geo/MElement.h
+++ b/Geo/MElement.h
@@ -385,6 +385,7 @@ class MElement
   virtual void writeTOCHNOG(FILE *fp, int num);
   virtual void writeMESH(FILE *fp, int elementTagType=1, int elementary=1,
                          int physical=0);
+  virtual void writeNEU(FILE *fp, unsigned gambitType, int adjust, int phys=0);
   virtual void writeIR3(FILE *fp, int elementTagType, int num, int elementary,
                         int physical);
   virtual void writeBDF(FILE *fp, int format=0, int elementTagType=1,
diff --git a/Geo/MVertex.cpp b/Geo/MVertex.cpp
index c56f6cedf6d4da65713d9930c95706a67d9028f6..cd1535f1d86152f204593e1963c6472f9c11bcb9 100644
--- a/Geo/MVertex.cpp
+++ b/Geo/MVertex.cpp
@@ -270,6 +270,26 @@ void MVertex::writeMESH(FILE *fp, double scalingFactor)
           _ge ? _ge->tag() : 0);
 }
 
+void MVertex::writeNEU(FILE *fp, int dim, double scalingFactor)
+{
+  if(_index < 0) return; // negative index vertices are never saved
+
+  switch(dim) {
+  case 3:
+    fprintf(fp, "%10d%20.11e%20.11e%20.11e\n",
+            _index, x() * scalingFactor, y() * scalingFactor,
+            z() * scalingFactor);
+    break;
+  case 2:
+    fprintf(fp, "%10d%20.11e%20.11e\n",
+            _index, x() * scalingFactor, y() * scalingFactor);
+    break;
+  case 1:
+    fprintf(fp, "%10d%20.11e\n", _index, x() * scalingFactor);
+    break;
+  }
+}
+
 static void double_to_char8(double val, char *str)
 {
   if(val >= 1.e6)
diff --git a/Geo/MVertex.h b/Geo/MVertex.h
index 0467a86606a63e5efab81e3e8687b247d235ac67..df093d162aa6a33fc6606b177298adeb8f03724d 100644
--- a/Geo/MVertex.h
+++ b/Geo/MVertex.h
@@ -100,6 +100,7 @@ class MVertex{
                 bool bigEndian=false);
   void writeTOCHNOG(FILE *fp, int dim, double scalingFactor=1.0);
   void writeMESH(FILE *fp, double scalingFactor=1.0);
+  void writeNEU(FILE *fp, int dim, double scalingFactor=1.0);
   void writeBDF(FILE *fp, int format=0, double scalingFactor=1.0);
   void writeINP(FILE *fp, double scalingFactor=1.0);
   void writeDIFF(FILE *fp, bool binary, double scalingFactor=1.0);