diff --git a/Geo/GModelIO_TOCHNOG.cpp b/Geo/GModelIO_TOCHNOG.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..587b0e873800b75f32f8a3f143cd3ea4e5341dc4
--- /dev/null
+++ b/Geo/GModelIO_TOCHNOG.cpp
@@ -0,0 +1,186 @@
+// Gmsh - Copyright (C) 1997-2015 C. Geuzaine, J.-F. Remacle
+//
+// Authors: Roman Putanowicz and Fernando Lorenzo
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to the public mailing list <gmsh@geuz.org>.
+
+#include "OS.h"
+#include "MPoint.h"
+#include "MLine.h"
+#include "MTriangle.h"
+#include "MQuadrangle.h"
+#include "MTetrahedron.h"
+#include "MHexahedron.h"
+#include "StringUtils.h"
+#include "GModel.h"
+
+int dimension;
+
+template <class T>
+static void writeElementsTOCHNOG(FILE *fp, GEntity *ge, std::vector<T*> &elements,
+                                 bool saveAll)
+{
+  if(elements.size() && (saveAll || ge->physicals.size())){
+    const char *typ = elements[0]->getStringForTOCHNOG();
+    if(typ){
+      //const char *str = (ge->dim() == 3) ? " 3 " : (ge->dim() == 2) ?
+      //  " 2 " : (ge->dim() == 1) ? " 1 " : "Point";
+      //fprintf(fp, "( 'number_of_space_dimensions   %s)\n", str);
+      for(unsigned int i = 0; i < elements.size(); i++)
+        elements[i]->writeTOCHNOG(fp, elements[i]->getNum());
+    }
+  }
+}
+
+static std::string physicalName(GModel *m, int dim, int num)
+{
+  std::string name = m->getPhysicalName(dim, num);
+  if(name.empty()){
+    char tmp[256];
+    sprintf(tmp, "%s%d", (dim == 3) ? "PhysicalVolume" :
+            (dim == 2) ? "PhysicalSurface" : "PhysicalLine", num);
+    name = tmp;
+  }
+  for(unsigned int i = 0; i < name.size(); i++)
+    if(name[i] == ' ') name[i] = '_';
+  return name;
+}
+
+int GModel::writeTOCHNOG(const std::string &name, bool saveAll, bool saveGroupsOfNodes,
+                         double scalingFactor)
+{
+  FILE *fp = Fopen(name.c_str(), "w");
+  if(!fp){
+    Msg::Error("Unable to open file '%s'", name.c_str());
+    return 0;
+  }
+
+  fprintf(fp, "(----Tochnog Input File Created by Gmsh Version 2.13.1 ----)\n");
+  fprintf(fp, " \n");
+  fprintf(fp,  "(**EDIT OR MODIFY THE ENTRIES BELOW AS REQUIRED**)\n"
+          "echo  -yes \n"
+          "number of space dimensions (add number here) \n"
+          "derivatives \n"
+          "materi_velocity \n"
+          "materi_displacement \n"
+          "materi_strain_total  \n"
+          "materi_stress  \n"
+          "condif_temperature \n"
+          "number_of_integration_points (add number here) \n"
+          "end_initia \n"
+          "options_element_dof -yes  \n");
+  fprintf(fp, "\n");
+
+  // Nodes
+  /* Save vertices */
+  fprintf(fp, "(----------------Nodes----------------)\n");
+  fprintf(fp, "\n");
+  int dim = getDim();
+  if(noPhysicalGroups()) saveAll = true;
+
+  indexMeshVertices(saveAll);
+  std::vector<GEntity*> entities;
+  getEntities(entities);
+
+  for(unsigned int i = 0; i < entities.size(); i++)
+    for(unsigned int j = 0; j < entities[i]->mesh_vertices.size(); j++)
+      entities[i]->mesh_vertices[j]->writeTOCHNOG(fp, dim, scalingFactor);
+  fprintf(fp, "\n");
+  // Nodes
+  // Elements
+  fprintf(fp, "(++++++++++++++ E L E M E N T S ++++++++++++++)\n");
+  fprintf(fp, "\n");
+  for(viter it = firstVertex(); it != lastVertex(); ++it){
+    writeElementsTOCHNOG(fp, *it, (*it)->points, saveAll);
+  }
+
+  if (dim ==3) {
+    for(riter it = firstRegion(); it != lastRegion(); ++it){
+      writeElementsTOCHNOG(fp, *it, (*it)->tetrahedra, saveAll);
+      writeElementsTOCHNOG(fp, *it, (*it)->hexahedra, saveAll);
+    }
+  }
+  else if (dim ==2) {
+    for(fiter it = firstFace(); it != lastFace(); ++it){
+      writeElementsTOCHNOG(fp, *it, (*it)->triangles, saveAll);
+      writeElementsTOCHNOG(fp, *it, (*it)->quadrangles, saveAll);
+    }
+  }
+  else if (dim ==1) {
+    for(eiter it = firstEdge(); it != lastEdge(); ++it){
+      writeElementsTOCHNOG(fp, *it, (*it)->lines, saveAll);
+    }
+  }
+
+  fprintf(fp, "\n");
+
+  // Elements
+
+  std::map<int, std::vector<GEntity*> > groups[4];
+  getPhysicalGroups(groups);
+  fprintf(fp, "( +------------+---------Physical Groups Section----------+------------+\n");
+  fprintf(fp, "\n");
+  fprintf(fp, "- In Tochnog use Physical Groups to define 'element_group' entities to  -\n");
+  fprintf(fp, "- identify materials, and groups of nodes to apply boundary conditions -)\n");
+  fprintf(fp, "\n");
+  fprintf(fp, "(- For example, groups of ELEMENTS chosen using gmsh 'physical groups' can be used as follows)\n");
+  fprintf(fp, "(- element_group  -ra INSERT HERE GROUP OF ELEMENTS SAVED WITH GMSH -ra  Material number)\n");
+  fprintf(fp, "\n");
+  fprintf(fp, "(- For example, groups of nodes chosen using gmsh 'physical groups' can be used as follows)\n");
+  fprintf(fp, "(- bounda_unknown 0  -ra INSERT HERE GROUP OF NODES SAVED WITH GMSH -ra   -velx -vely )\n");
+  fprintf(fp, "(- bounda_time 0      0.000      0.000 1000000.000      0.000 )\n");
+  fprintf(fp, "\n");
+  fprintf(fp, "( +------------+---------Physical Groups Section----------+------------+\n");
+
+  // Save elements sets for each physical group
+  for(int dim = 1; dim <= 3; dim++){
+    for(std::map<int, std::vector<GEntity*> >::iterator it = groups[dim].begin();
+        it != groups[dim].end(); it++){
+      std::vector<GEntity *> &entities = it->second;
+      fprintf(fp, "\n");
+      fprintf(fp, "(Element sets ===> 'element_group' to identify DIFFERENT MATERIALS =%s)\n", physicalName(this, dim, it->first).c_str());
+      int n = 0;
+      for(unsigned int i = 0; i < entities.size(); i++){
+        for(unsigned int j = 0; j < entities[i]->getNumMeshElements(); j++){
+          MElement *e = entities[i]->getMeshElement(j);
+          if(n && !(n % 10)) fprintf(fp, "\n");
+          fprintf(fp, "%d ", e->getNum());
+          n++;
+        }
+      }
+      fprintf(fp, "\n");
+    }
+  }
+
+  // Save node sets for each physical group
+  if(saveGroupsOfNodes){
+    for(int dim = 1; dim <= 3; dim++){
+      for(std::map<int, std::vector<GEntity*> >::iterator it = groups[dim].begin();
+          it != groups[dim].end(); it++){
+        std::set<MVertex*> nodes;
+        std::vector<GEntity *> &entities = it->second;
+        for(unsigned int i = 0; i < entities.size(); i++){
+          for(unsigned int j = 0; j < entities[i]->getNumMeshElements(); j++){
+            MElement *e = entities[i]->getMeshElement(j);
+            for (int k = 0; k < e->getNumVertices(); k++)
+              nodes.insert(e->getVertex(k));
+          }
+        }
+        fprintf(fp, "\n");
+        fprintf(fp, "(Node sets ===> Used to set BOUNDARY CONDITIONS in Tochnog =%s)\n", physicalName(this, dim, it->first).c_str());
+        fprintf(fp, "\n");
+        int n = 0;
+        for(std::set<MVertex*>::iterator it2 = nodes.begin(); it2 != nodes.end(); it2++){
+          if(n && !(n % 10)) fprintf(fp, "\n");
+          fprintf(fp, "%d ", (*it2)->getIndex());
+          n++;
+        }
+        fprintf(fp, "\n");
+      }
+    }
+  }
+
+  fclose(fp);
+  return 1;
+}