diff --git a/CMakeLists.txt b/CMakeLists.txt
index a1335759971411fa62f8167e6231828eaad5f2d0..2be515dcd012c547d039dcdefeb4153ede1aede8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -53,7 +53,7 @@ opt(GETDP "Enable GetDP solver (as a directly linked library)" ${DEFAULT})
 opt(GMM "Enable GMM linear solvers (simple alternative to PETSc)" ${DEFAULT})
 opt(GMP "Enable GMP for Kbipack (advanced)" ON)
 opt(GRAPHICS "Enable building graphics lib even without GUI (advanced)" OFF)
-opt(INTERNAL_DEVELOPER_API "Enable internal developer API (will be off by default)" ON)
+opt(INTERNAL_DEVELOPER_API "Enable internal developer API" OFF)
 opt(KBIPACK "Enable Kbipack (neeeded by homology solver)" ${DEFAULT})
 opt(MATHEX "Enable math expression parser (used by plugins and options)" ${DEFAULT})
 opt(MED "Enable MED mesh and post file formats" ${DEFAULT})
@@ -105,75 +105,22 @@ set(GMSH_SHORT_LICENSE "GNU General Public License")
 
 set(GMSH_API Common/gmsh.h)
 
-set(GMSH_INTERNAL_DEVELOPER_API
-  ${CMAKE_CURRENT_BINARY_DIR}/Common/GmshConfig.h
-  ${CMAKE_CURRENT_BINARY_DIR}/Common/GmshVersion.h
-  Common/GmshGlobal.h Common/Context.h Common/GmshDefines.h Common/GmshMessage.h
-    Common/VertexArray.h Common/Octree.h Common/OctreeInternals.h Common/OS.h
-    Common/StringUtils.h Common/OpenFile.h Common/Hash.h Common/onelab.h
-    Common/GmshSocket.h Common/onelabUtils.h Common/Options.h Common/picojson.h
-  Numeric/Numeric.h Numeric/GaussIntegration.h Numeric/polynomialBasis.h
-    Numeric/JacobianBasis.h Numeric/bezierBasis.h Numeric/fullMatrix.h
-    Numeric/FuncSpaceData.h Numeric/pointsGenerators.h Numeric/simpleFunction.h
-    Numeric/cartesian.h Numeric/ElementType.h Numeric/BasisFactory.h
-    Numeric/CondNumBasis.h Numeric/mathEvaluator.h Numeric/nodalBasis.h
-  Geo/GModel.h Geo/GEntity.h Geo/GPoint.h Geo/GVertex.h Geo/GEdge.h Geo/GFace.h
-    Geo/GRegion.h Geo/GEdgeLoop.h Geo/MVertex.h Geo/MVertexBoundaryLayerData.h
-    Geo/MEdge.h Geo/MFace.h Geo/MEdgeHash.h Geo/MFaceHash.h Geo/MElement.h
-    Geo/MElementOctree.h Geo/MPoint.h Geo/MLine.h Geo/MTriangle.h
-    Geo/MQuadrangle.h Geo/MTetrahedron.h Geo/MHexahedron.h Geo/MPrism.h
-    Geo/MPyramid.h Geo/MTrihedron.h Geo/MElementCut.h Geo/discreteVertex.h
-    Geo/discreteEdge.h Geo/discreteFace.h Geo/discreteRegion.h Geo/SPoint2.h
-    Geo/SPoint3.h Geo/SVector3.h Geo/STensor3.h Geo/SBoundingBox3d.h Geo/Pair.h
-    Geo/Range.h Geo/SOrientedBoundingBox.h Geo/CellComplex.h Geo/ChainComplex.h
-    Geo/Cell.h Geo/Homology.h Geo/Chain.h Geo/GenericVertex.h Geo/GenericEdge.h
-    Geo/GenericFace.h Geo/GenericRegion.h Geo/partitionVertex.h
-    Geo/partitionEdge.h Geo/partitionFace.h Geo/CGNSOptions.h Geo/gmshLevelset.h
-    Geo/boundaryLayersData.h
-  Mesh/meshGEdge.h Mesh/meshGFace.h Mesh/meshGFaceOptimize.h
-    Mesh/meshPartition.h Mesh/meshGFaceDelaunayInsertion.h Mesh/simple3D.h
-    Mesh/meshPartitionOptions.h Mesh/directions3D.h Mesh/yamakawa.h
-    Mesh/Voronoi3D.h Mesh/Levy3D.h Mesh/meshMetric.h Mesh/ThinLayer.h
-  Solver/dofManager.h Solver/femTerm.h Solver/laplaceTerm.h
-    Solver/elasticityTerm.h Solver/crossConfTerm.h Solver/orthogonalTerm.h
-    Solver/linearSystem.h Solver/linearSystemGMM.h Solver/linearSystemCSR.h
-    Solver/linearSystemFull.h Solver/elasticitySolver.h Solver/sparsityPattern.h
-    Solver/groupOfElements.h Solver/linearSystemPETSc.h
-    Solver/linearSystemMUMPS.h Solver/thermicSolver.h
-  Post/PView.h Post/PViewData.h Plugin/PluginManager.h Post/OctreePost.h
-    Post/PViewDataList.h Post/PViewDataGModel.h Post/PViewOptions.h
-    Post/ColorTable.h Post/adaptiveData.h
-  Graphics/drawContext.h
-  contrib/kbipack/gmp_normal_form.h contrib/kbipack/gmp_matrix.h
-    contrib/kbipack/gmp_blas.h contrib/kbipack/mpz.h
-  contrib/DiscreteIntegration/Integration3D.h
-    contrib/HighOrderMeshOptimizer/OptHOM.h
-    contrib/HighOrderMeshOptimizer/OptHomMesh.h
-    contrib/HighOrderMeshOptimizer/OptHomRun.h
-    contrib/HighOrderMeshOptimizer/ParamCoord.h
-    contrib/HighOrderMeshOptimizer/OptHomFastCurving.h
-    contrib/HighOrderMeshOptimizer/BoundaryLayerCurver.h
-    contrib/HighOrderMeshOptimizer/OptHomIntegralBoundaryDist.h
-    contrib/HighOrderMeshOptimizer/CADDistances.h
-    contrib/HighOrderMeshOptimizer/OptHomObjContribScaledJac.h
-    contrib/HighOrderMeshOptimizer/OptHomObjContribMetricMin.h
-    contrib/HighOrderMeshOptimizer/OptHomObjContribCADDist.h
-  contrib/MeshOptimizer/MeshOptPatch.h contrib/MeshOptimizer/MeshOpt.h
-    contrib/MeshOptimizer/MeshOptCommon.h contrib/MeshOptimizer/MeshOptimizer.h
-    contrib/MeshOptimizer/MeshOptObjContribFunc.h
-    contrib/MeshOptimizer/MeshOptObjContrib.h
-    contrib/MeshOptimizer/MeshOptObjContribScaledNodeDispSq.h
-    contrib/MeshOptimizer/MeshOptObjectiveFunction.h
-    contrib/MeshOptimizer/MeshOptVertexCoord.h
-  contrib/MeshQualityOptimizer/MeshQualityObjContribIdealJac.h
-    contrib/MeshQualityOptimizer/MeshQualityObjContribInvCond.h
-    contrib/MeshQualityOptimizer/MeshQualityOptimizer.h 
-  contrib/MathEx/mathex.h)
-
-get_property(IAMCHILD DIRECTORY  PROPERTY PARENT_DIRECTORY)
-if(IAMCHILD)
-  set(GMSH_INTERNAL_DEVELOPER_API ${GMSH_API} PARENT_SCOPE)
-endif(IAMCHILD)
+if(ENABLE_INTERNAL_DEVELOPER_API)
+  message(WARNING "The internal developer API is unsupported and undocumented. "
+      "It is meant for Gmsh (and related projects) developers, not for wide "
+      "distribution. If you are packaging Gmsh for redistribution, please "
+      "DO NOT enable this and just ship the stable API (${GMSH_API}) instead.")
+  file(GLOB_RECURSE HEADERS Common/*.h Numeric/*.h Geo/*.h Mesh/*.h Solver/*.h 
+    Post/*.h Graphics/*.h contrib/kbipack/*.h contrib/DiscreteIntegration/*.h
+    contrib/HighOrderMeshOptimizer/*.h contrib/MeshOptimizer/*.h
+    contrib/MeshQualityOptimizer/*.h contrib/MathEx/*.h)
+  set(GMSH_INTERNAL_DEVELOPER_API ${CMAKE_CURRENT_BINARY_DIR}/Common/GmshConfig.h
+      ${CMAKE_CURRENT_BINARY_DIR}/Common/GmshVersion.h ${HEADERS})
+  get_property(IAMCHILD DIRECTORY  PROPERTY PARENT_DIRECTORY)
+  if(IAMCHILD)
+    set(GMSH_INTERNAL_DEVELOPER_API ${GMSH_API} PARENT_SCOPE)
+  endif(IAMCHILD)
+endif(ENABLE_INTERNAL_DEVELOPER_API)
 
 if(${CMAKE_MAJOR_VERSION} GREATER 2)
   string(TIMESTAMP DATE "%Y%m%d")
@@ -446,7 +393,7 @@ if(ENABLE_BLAS_LAPACK)
     endif(NOT HAVE_BLAS OR NOT HAVE_LAPACK)
 
     if(NOT HAVE_BLAS OR NOT HAVE_LAPACK)
-      message(STATUS "Warning: Could not find Blas or Lapack: most meshing algorithms "
+      message(WARNING "Could not find Blas or Lapack: most meshing algorithms "
               "will not be functional")
     endif(NOT HAVE_BLAS OR NOT HAVE_LAPACK)
 
@@ -1074,7 +1021,7 @@ if(HAVE_SOLVER)
       set_source_files_properties(${TAUCS_G} PROPERTIES COMPILE_FLAGS -DTAUCS_CORE_GENERAL)
       set_config_option(HAVE_TAUCS "Taucs")
     else(HAVE_METIS)
-      message(STATUS "Warning: Disabling Taucs (requires METIS)")
+      message(WARNING "Disabling Taucs (requires METIS)")
     endif(HAVE_METIS)
   endif(ENABLE_TAUCS AND HAVE_BLAS AND HAVE_LAPACK)
 
@@ -1145,9 +1092,9 @@ if(ENABLE_OCC)
     endif(OCC_MAJOR AND OCC_MINOR AND OCC_MAINT)
   endif(OCC_INC)
   if(OCC_VERSION AND OCC_VERSION STRLESS ${OCC_MINIMAL_VERSION})
-    message(WARNING "Gmsh requires OpenCASCADE >= ${OCC_MINIMAL_VERSION}")
-    message(WARNING "Use CMAKE_PREFIX_PATH or the CASROOT environment variable "
-            "to explicitely specify the installation path of OpenCASCADE")
+    message(WARNING "Gmsh requires OpenCASCADE >= ${OCC_MINIMAL_VERSION}. "
+        "Use CMAKE_PREFIX_PATH or the CASROOT environment variable "
+        "to explicitely specify the installation path of OpenCASCADE")
   else(OCC_VERSION AND OCC_VERSION STRLESS ${OCC_MINIMAL_VERSION})
     set(OCC_LIBS_REQUIRED
 	# subset of DataExchange
@@ -1267,7 +1214,11 @@ if(ENABLE_WRAP_PYTHON)
     include_directories(${CMAKE_CURRENT_SOURCE_DIR})
     set(CMAKE_SWIG_FLAGS "")
     set_source_files_properties(Common/gmsh.i PROPERTIES CPLUSPLUS ON)
-    swig_add_module(gmsh python Common/gmsh.i)
+    if(${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 3.8)
+      swig_add_library(gmsh LANGUAGE python SOURCES Common/gmsh.i)
+    else(${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 3.8)
+      swig_add_module(gmsh python Common/gmsh.i)
+    endif(${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 3.8)
     swig_link_libraries(gmsh ${PYTHON_LIBRARIES} shared)
     if(APPLE)
       set_target_properties("_gmsh" PROPERTIES LINK_FLAGS
diff --git a/Common/Context.h b/Common/Context.h
index e9121396c3ead20d5a6057fc4162cfd22a45ba16..fe4f8d27eb70850ade6c7871ab9c1e3506a7cb77 100644
--- a/Common/Context.h
+++ b/Common/Context.h
@@ -260,6 +260,7 @@ class CTX {
     int draw, link, horizontalScales;
     int smooth, animCycle, animStep, combineTime, combineRemoveOrig;
     int fileFormat, plugins, forceNodeData, forceElementData;
+    int saveMesh, saveInterpolationMatrices;
     double animDelay;
     std::string doubleClickedGraphPointCommand;
     double doubleClickedGraphPointX, doubleClickedGraphPointY;
diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h
index ffe67a003ff4b06ed14ef47627538b7fd9ae7b29..830a865ed45b2dfc36db6bf48c6824af52477fea 100644
--- a/Common/DefaultOptions.h
+++ b/Common/DefaultOptions.h
@@ -966,12 +966,7 @@ StringXNumber GeometryOptions_Number[] = {
 StringXNumber MeshOptions_Number[] = {
   { F|O, "Algorithm" , opt_mesh_algo2d , ALGO_2D_AUTO ,
     "2D mesh algorithm (1=MeshAdapt, 2=Automatic, 5=Delaunay, 6=Frontal, 7=BAMG, 8=DelQuad)" },
-  { F|O, "Algorithm3D" , opt_mesh_algo3d ,
-#if defined(HAVE_TETGEN)
-    ALGO_3D_DELAUNAY ,
-#else
-    ALGO_3D_DELAUNAY_NEW ,
-#endif
+  { F|O, "Algorithm3D" , opt_mesh_algo3d , ALGO_3D_DELAUNAY_NEW ,
     "3D mesh algorithm (1=Delaunay, 2=New Delaunay, 4=Frontal, 5=Frontal Delaunay, "
     "6=Frontal Hex, 7=MMG3D, 9=R-tree)" },
   { F|O, "AngleSmoothNormals" , opt_mesh_angle_smooth_normals , 30.0 ,
@@ -1400,6 +1395,10 @@ StringXNumber PostProcessingOptions_Number[] = {
   { F|O, "Plugins" , opt_post_plugins , 1. ,
     "Enable default post-processing plugins?" },
 
+  { F|O, "SaveInterpolationMatrices" , opt_post_save_interpolation_matrices , 1. ,
+    "Save the interpolation matrices when exporting model-based data" },
+  { F|O, "SaveMesh" , opt_post_save_mesh , 1. ,
+    "Save the mesh when exporting model-based data" },
   { F|O, "Smoothing" , opt_post_smooth , 0. ,
     "Apply (non-reversible) smoothing to post-processing view when merged" },
 
diff --git a/Common/Options.cpp b/Common/Options.cpp
index ad0e613df34e6960c02cabb27d6c7af608f69af5..22ffa0bbc2101ad51ea59b0c868edc0bb8f06b4f 100644
--- a/Common/Options.cpp
+++ b/Common/Options.cpp
@@ -6862,6 +6862,20 @@ double opt_post_force_element_data(OPT_ARGS_NUM)
   return CTX::instance()->post.forceElementData;
 }
 
+double opt_post_save_mesh(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET)
+    CTX::instance()->post.saveMesh = (int)val;
+  return CTX::instance()->post.saveMesh;
+}
+
+double opt_post_save_interpolation_matrices(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET)
+    CTX::instance()->post.saveInterpolationMatrices = (int)val;
+  return CTX::instance()->post.saveInterpolationMatrices;
+}
+
 double opt_post_double_clicked_graph_point_x(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
diff --git a/Common/Options.h b/Common/Options.h
index 12b9a3e5e2c366be1bf9cad79154e25d3234dbed..c2260bef4cef479aa3a48f094806165928b405c3 100644
--- a/Common/Options.h
+++ b/Common/Options.h
@@ -582,6 +582,8 @@ double opt_post_nb_views(OPT_ARGS_NUM);
 double opt_post_file_format(OPT_ARGS_NUM);
 double opt_post_force_node_data(OPT_ARGS_NUM);
 double opt_post_force_element_data(OPT_ARGS_NUM);
+double opt_post_save_mesh(OPT_ARGS_NUM);
+double opt_post_save_interpolation_matrices(OPT_ARGS_NUM);
 double opt_post_double_clicked_graph_point_x(OPT_ARGS_NUM);
 double opt_post_double_clicked_graph_point_y(OPT_ARGS_NUM);
 double opt_post_double_clicked_view(OPT_ARGS_NUM);
diff --git a/Common/gmsh.cpp b/Common/gmsh.cpp
index d7e309a145f86a27f9e27c628af2a31a51008bf4..bffea8b6ab1a0c77b1ae453b8c20164be2d12002 100644
--- a/Common/gmsh.cpp
+++ b/Common/gmsh.cpp
@@ -34,7 +34,17 @@
 #include "Field.h"
 #endif
 
-#define GMSH_ERROR(n) { throw n; }
+#if defined(HAVE_POST)
+#include "PView.h"
+#include "PViewData.h"
+#include "PViewDataList.h"
+#include "PViewDataGModel.h"
+#include "PViewOptions.h"
+#endif
+
+#if defined(HAVE_PLUGINS)
+#include "PluginManager.h"
+#endif
 
 static int _initialized = 0;
 
@@ -51,59 +61,59 @@ static bool _isInitialized()
 
 // gmsh
 
-void gmshInitialize(int argc, char **argv)
+void gmsh::initialize(int argc, char **argv)
 {
   if(_initialized){
     Msg::Error("Gmsh has aleady been initialized");
-    GMSH_ERROR(1);
+    throw 1;
   }
   if(GmshInitialize(argc, argv)){
     _initialized = 1;
     return;
   }
-  GMSH_ERROR(-1);
+  throw -1;
 }
 
-void gmshFinalize()
+void gmsh::finalize()
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   if(GmshFinalize()){
     _initialized = 0;
     return;
   }
   Msg::Error("Something went wrong when finalizing Gmsh");
-  GMSH_ERROR(1);
+  throw 1;
 }
 
-void gmshOpen(const std::string &fileName)
+void gmsh::open(const std::string &fileName)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   if(GmshOpenProject(fileName)) return;
-  GMSH_ERROR(1);
+  throw 1;
 }
 
-void gmshMerge(const std::string &fileName)
+void gmsh::merge(const std::string &fileName)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   if(GmshMergeFile(fileName)) return;
-  GMSH_ERROR(1);
+  throw 1;
 }
 
-void gmshExport(const std::string &fileName)
+void gmsh::write(const std::string &fileName)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   if(GmshWriteFile(fileName)) return;
-  GMSH_ERROR(1);
+  throw 1;
 }
 
-void gmshClear()
+void gmsh::clear()
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   if(GmshClearProject()) return;
-  GMSH_ERROR(1);
+  throw 1;
 }
 
-// gmshOption
+// gmsh::option
 
 static void _splitOptionName(const std::string &fullName, std::string &category,
                              std::string &name, int &index)
@@ -130,81 +140,81 @@ static void _splitOptionName(const std::string &fullName, std::string &category,
              name.c_str(), index);
 }
 
-void gmshOptionSetNumber(const std::string &name, const double value)
+void gmsh::option::setNumber(const std::string &name, const double value)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   std::string c, n;
   int i;
   _splitOptionName(name, c, n, i);
   if(GmshSetOption(c, n, value, i)) return;
-  GMSH_ERROR(1);
+  throw 1;
 }
 
-void gmshOptionGetNumber(const std::string &name, double &value)
+void gmsh::option::getNumber(const std::string &name, double &value)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   std::string c, n;
   int i;
   _splitOptionName(name, c, n, i);
   if(GmshGetOption(c, n, value, i)) return;
-  GMSH_ERROR(1);
+  throw 1;
 }
 
-void gmshOptionSetString(const std::string &name, const std::string &value)
+void gmsh::option::setString(const std::string &name, const std::string &value)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   std::string c, n;
   int i;
   _splitOptionName(name, c, n, i);
   if(GmshSetOption(c, n, value, i)) return;
-  GMSH_ERROR(1);
+  throw 1;
 }
 
-void gmshOptionGetString(const std::string &name, std::string &value)
+void gmsh::option::getString(const std::string &name, std::string &value)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   std::string c, n;
   int i;
   _splitOptionName(name, c, n, i);
   if(GmshGetOption(c, n, value, i)) return;
-  GMSH_ERROR(1);
+  throw 1;
 }
 
-// gmshModel
+// gmsh::model
 
-void gmshModelCreate(const std::string &name)
+void gmsh::model::add(const std::string &name)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   GModel *m = new GModel(name);
-  if(!m){ GMSH_ERROR(1); }
+  if(!m){ throw 1; }
 }
 
-void gmshModelDelete()
+void gmsh::model::remove()
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   GModel *m = GModel::current();
-  if(!m){ GMSH_ERROR(1); }
+  if(!m){ throw 1; }
   delete m;
 }
 
-void gmshModelList(std::vector<std::string> &names)
+void gmsh::model::list(std::vector<std::string> &names)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   for(unsigned int i = 0; i < GModel::list.size(); i++)
     names.push_back(GModel::list[i]->getName());
 }
 
-void gmshModelSetCurrent(const std::string &name)
+void gmsh::model::setCurrent(const std::string &name)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   GModel *m = GModel::findByName(name);
-  if(!m){ GMSH_ERROR(1); }
+  if(!m){ throw 1; }
   GModel::setCurrent(m);
 }
 
-void gmshModelGetEntities(vector_pair &dimTags, const int dim)
+void gmsh::model::getEntities(vector_pair &dimTags, const int dim)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   dimTags.clear();
   std::vector<GEntity*> entities;
   GModel::current()->getEntities(entities, dim);
@@ -212,9 +222,9 @@ void gmshModelGetEntities(vector_pair &dimTags, const int dim)
     dimTags.push_back(std::pair<int, int>(entities[i]->dim(), entities[i]->tag()));
 }
 
-void gmshModelGetPhysicalGroups(vector_pair &dimTags, const int dim)
+void gmsh::model::getPhysicalGroups(vector_pair &dimTags, const int dim)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   dimTags.clear();
   std::map<int, std::vector<GEntity*> > groups[4];
   GModel::current()->getPhysicalGroups(groups);
@@ -227,10 +237,10 @@ void gmshModelGetPhysicalGroups(vector_pair &dimTags, const int dim)
   }
 }
 
-void gmshModelGetEntitiesForPhysicalGroup(const int dim, const int tag,
-                                          std::vector<int> &tags)
+void gmsh::model::getEntitiesForPhysicalGroup(const int dim, const int tag,
+                                              std::vector<int> &tags)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   tags.clear();
   std::map<int, std::vector<GEntity*> > groups;
   GModel::current()->getPhysicalGroups(dim, groups);
@@ -241,52 +251,52 @@ void gmshModelGetEntitiesForPhysicalGroup(const int dim, const int tag,
   }
 }
 
-int gmshModelAddPhysicalGroup(const int dim, const std::vector<int> &tags,
-                              const int tag)
+int gmsh::model::addPhysicalGroup(const int dim, const std::vector<int> &tags,
+                                  const int tag)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   int outTag = tag;
   if(outTag < 0)
     outTag = GModel::current()->getGEOInternals()->getMaxPhysicalTag() + 1;
   if(!GModel::current()->getGEOInternals()->modifyPhysicalGroup
      (dim, outTag, 0, tags)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   GModel::current()->getGEOInternals()->synchronize(GModel::current());
   return outTag;
 }
 
-void gmshModelSetPhysicalName(const int dim, const int tag,
-                              const std::string &name)
+void gmsh::model::setPhysicalName(const int dim, const int tag,
+                                  const std::string &name)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   GModel::current()->setPhysicalName(name, dim, tag);
 }
 
-void gmshModelGetPhysicalName(const int dim, const int tag, std::string &name)
+void gmsh::model::getPhysicalName(const int dim, const int tag, std::string &name)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   name = GModel::current()->getPhysicalName(dim, tag);
 }
 
-void gmshModelGetBoundary(const vector_pair &dimTags, vector_pair &outDimTags,
-                          const bool combined, const bool oriented,
-                          const bool recursive)
+void gmsh::model::getBoundary(const vector_pair &dimTags, vector_pair &outDimTags,
+                              const bool combined, const bool oriented,
+                              const bool recursive)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   outDimTags.clear();
   if(!GModel::current()->getBoundaryTags(dimTags, outDimTags, combined,
                                          oriented, recursive)){
-    GMSH_ERROR(1);
+    throw 1;
   }
 }
 
-void gmshModelGetEntitiesInBoundingBox(const double xmin, const double ymin,
-                                       const double zmin, const double xmax,
-                                       const double ymax, const double zmax,
-                                       vector_pair &dimTags, const int dim)
+void gmsh::model::getEntitiesInBoundingBox(const double xmin, const double ymin,
+                                           const double zmin, const double xmax,
+                                           const double ymax, const double zmax,
+                                           vector_pair &dimTags, const int dim)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   dimTags.clear();
   SBoundingBox3d box(xmin, ymin, zmin, xmax, ymax, zmax);
   std::vector<GEntity*> entities;
@@ -308,18 +318,18 @@ static std::string _entityName(int dim, int tag)
   return stream.str();
 }
 
-void gmshModelGetBoundingBox(const int dim, const int tag, double &xmin,
-                             double &ymin, double &zmin, double &xmax,
-                             double &ymax, double &zmax)
+void gmsh::model::getBoundingBox(const int dim, const int tag, double &xmin,
+                                 double &ymin, double &zmin, double &xmax,
+                                 double &ymax, double &zmax)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   GEntity *ge = GModel::current()->getEntityByTag(dim, tag);
   if(!ge){
     Msg::Error("%s does not exist", _entityName(dim, tag).c_str());
-    GMSH_ERROR(2);
+    throw 2;
   }
   SBoundingBox3d box = ge->bounds();
-  if(box.empty()){ GMSH_ERROR(3); }
+  if(box.empty()){ throw(3); }
   xmin = box.min().x();
   ymin = box.min().y();
   zmin = box.min().z();
@@ -328,10 +338,10 @@ void gmshModelGetBoundingBox(const int dim, const int tag, double &xmin,
   zmax = box.max().z();
 }
 
-int gmshModelAddDiscreteEntity(const int dim, const int tag,
-                               const std::vector<int> &boundary)
+int gmsh::model::addDiscreteEntity(const int dim, const int tag,
+                                   const std::vector<int> &boundary)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   int outTag = tag;
   if(outTag < 0){
     outTag = GModel::current()->getMaxElementaryNumber(dim);
@@ -339,7 +349,7 @@ int gmshModelAddDiscreteEntity(const int dim, const int tag,
   GEntity *e = GModel::current()->getEntityByTag(dim, outTag);
   if(e){
     Msg::Error("%s already exists", _entityName(dim, outTag).c_str());
-    GMSH_ERROR(2);
+    throw 2;
   }
   // FIXME: check and set boundary entities to construct topology!
   switch(dim){
@@ -365,37 +375,57 @@ int gmshModelAddDiscreteEntity(const int dim, const int tag,
     break;
   }
   default :
-    GMSH_ERROR(2);
+    throw 2;
   }
   return outTag;
 }
 
-void gmshModelRemove(const vector_pair &dimTags, const bool recursive)
+void gmsh::model::removeEntities(const vector_pair &dimTags, const bool recursive)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   GModel::current()->remove(dimTags, recursive);
 }
 
-void gmshModelMesh(int dim)
+// gmsh::model::mesh
+
+void gmsh::model::mesh::generate(int dim)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   GModel *m = GModel::current();
-  if(!m){ GMSH_ERROR(1); }
+  if(!m){ throw 1; }
   m->mesh(dim);
 }
 
-void gmshModelGetMeshVertices(const int dim, const int tag,
-                              std::vector<int> &vertexTags,
-                              std::vector<double> &coord,
-                              std::vector<double> &parametricCoord)
+void gmsh::model::mesh::getLastEntityError(vector_pair &dimTags)
+{
+  if(!_isInitialized()){ throw -1; }
+  std::vector<GEntity*> e = GModel::current()->getLastMeshEntityError();
+  dimTags.clear();
+  for(unsigned int i = 0; i < e.size(); i++)
+    dimTags.push_back(std::pair<int, int>(e[i]->dim(), e[i]->tag()));
+}
+
+void gmsh::model::mesh::getLastVertexError(std::vector<int> &vertexTags)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
+  std::vector<MVertex*> v = GModel::current()->getLastMeshVertexError();
+  vertexTags.clear();
+  for(unsigned int i = 0; i < v.size(); i++)
+    vertexTags.push_back(v[i]->getNum());
+}
+
+void gmsh::model::mesh::getVertices(const int dim, const int tag,
+                                    std::vector<int> &vertexTags,
+                                    std::vector<double> &coord,
+                                    std::vector<double> &parametricCoord)
+{
+  if(!_isInitialized()){ throw -1; }
   vertexTags.clear();
   coord.clear();
   GEntity *ge = GModel::current()->getEntityByTag(dim, tag);
   if(!ge){
     Msg::Error("%s does not exist", _entityName(dim, tag).c_str());
-    GMSH_ERROR(2);
+    throw 2;
   }
   for(unsigned int i = 0; i < ge->mesh_vertices.size(); i++){
     MVertex *v = ge->mesh_vertices[i];
@@ -428,19 +458,19 @@ static void _addElementInfo(const std::vector<T*> &ele,
   }
 }
 
-void gmshModelGetMeshElements(const int dim, const int tag,
-                              std::vector<int> &types,
-                              std::vector<std::vector<int> > &elementTags,
-                              std::vector<std::vector<int> > &vertexTags)
+void gmsh::model::mesh::getElements(const int dim, const int tag,
+                                    std::vector<int> &types,
+                                    std::vector<std::vector<int> > &elementTags,
+                                    std::vector<std::vector<int> > &vertexTags)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   types.clear();
   elementTags.clear();
   vertexTags.clear();
   GEntity *ge = GModel::current()->getEntityByTag(dim, tag);
   if(!ge){
     Msg::Error("%s does not exist", _entityName(dim, tag).c_str());
-    GMSH_ERROR(2);
+    throw 2;
   }
   switch(dim){
   case 0: {
@@ -466,26 +496,26 @@ void gmshModelGetMeshElements(const int dim, const int tag,
   }
 }
 
-void gmshModelSetMeshVertices(const int dim, const int tag,
-                              const std::vector<int> &vertexTags,
-                              const std::vector<double> &coord,
-                              const std::vector<double> &parametricCoord)
+void gmsh::model::mesh::setVertices(const int dim, const int tag,
+                                    const std::vector<int> &vertexTags,
+                                    const std::vector<double> &coord,
+                                    const std::vector<double> &parametricCoord)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   GEntity *ge = GModel::current()->getEntityByTag(dim, tag);
   if(!ge){
     Msg::Error("%s does not exist", _entityName(dim, tag).c_str());
-    GMSH_ERROR(2);
+    throw 2;
   }
   if(coord.size() != 3 * vertexTags.size()){
     Msg::Error("Wrong number of coord");
-    GMSH_ERROR(2);
+    throw 2;
   }
   bool param = false;
   if(parametricCoord.size()){
     if(parametricCoord.size() != dim * vertexTags.size()){
       Msg::Error("Wrong number of parametric coord");
-      GMSH_ERROR(2);
+      throw 2;
     }
     param = true;
   }
@@ -501,8 +531,8 @@ void gmshModelSetMeshVertices(const int dim, const int tag,
       vv = new MEdgeVertex(x, y, z, ge, u, n);
     }
     else if(param && dim == 2){
-      double u = parametricCoord[i];
-      double v = parametricCoord[i + 1];
+      double u = parametricCoord[2 * i];
+      double v = parametricCoord[2 * i + 1];
       vv = new MFaceVertex(x, y, z, ge, u, v, n);
     }
     else
@@ -522,24 +552,24 @@ static void _addElements(int dim, int tag, const std::vector<MElement*> &src,
     dst.push_back(static_cast<T*>(src[i]));
 }
 
-void gmshModelSetMeshElements(const int dim, const int tag,
-                              const std::vector<int> &types,
-                              const std::vector<std::vector<int> > &elementTags,
-                              const std::vector<std::vector<int> > &vertexTags)
+void gmsh::model::mesh::setElements(const int dim, const int tag,
+                                    const std::vector<int> &types,
+                                    const std::vector<std::vector<int> > &elementTags,
+                                    const std::vector<std::vector<int> > &vertexTags)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   GEntity *ge = GModel::current()->getEntityByTag(dim, tag);
   if(!ge){
     Msg::Error("%s does not exist", _entityName(dim, tag).c_str());
-    GMSH_ERROR(2);
+    throw 2;
   }
   if(types.size() != elementTags.size()){
     Msg::Error("Wrong number of element tags");
-    GMSH_ERROR(2);
+    throw 2;
   }
   if(types.size() != vertexTags.size()){
     Msg::Error("Wrong number of vertex tags");
-    GMSH_ERROR(2);
+    throw 2;
   }
   for(unsigned int i = 0; i < types.size(); i++){
     int type = types[i];
@@ -548,7 +578,7 @@ void gmshModelSetMeshElements(const int dim, const int tag,
     if(!numEle) continue;
     if(numEle * numVertPerEle != vertexTags[i].size()){
       Msg::Error("Wrong number of vertex tags for element type %d", type);
-      GMSH_ERROR(2);
+      throw 2;
     }
     std::vector<MElement*> elements(numEle);
     std::vector<MVertex*> vertices(numVertPerEle);
@@ -561,7 +591,7 @@ void gmshModelSetMeshElements(const int dim, const int tag,
         vertices[k] = GModel::current()->getMeshVertexByTag(vtag);
         if(!vertices[k]){
           Msg::Error("Unknown mesh vertex %d", vtag);
-          GMSH_ERROR(2);
+          throw 2;
         }
       }
       elements[j] = f.create(type, vertices, etag);
@@ -603,20 +633,20 @@ void gmshModelSetMeshElements(const int dim, const int tag,
     }
     if(!ok){
       Msg::Error("Wrong type of element for %s", _entityName(dim, tag).c_str());
-      GMSH_ERROR(2);
+      throw 2;
     }
   }
 }
 
-void gmshModelGetMeshVertex(const int vertexTag,
-                            std::vector<double> &coord,
-                            std::vector<double> &parametricCoord)
+void gmsh::model::mesh::getVertex(const int vertexTag,
+                                  std::vector<double> &coord,
+                                  std::vector<double> &parametricCoord)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   MVertex *v = GModel::current()->getMeshVertexByTag(vertexTag);
   if(!v){
     Msg::Error("Unknown mesh vertex %d", vertexTag);
-    GMSH_ERROR(2);
+    throw 2;
   }
   coord.clear();
   coord.push_back(v->x());
@@ -630,14 +660,14 @@ void gmshModelGetMeshVertex(const int vertexTag,
     parametricCoord.push_back(u);
 }
 
-void gmshModelGetMeshElement(const int elementTag, int &type,
-                             std::vector<int> &vertexTags)
+void gmsh::model::mesh::getElement(const int elementTag, int &type,
+                                   std::vector<int> &vertexTags)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   MElement *e = GModel::current()->getMeshElementByTag(elementTag);
   if(!e){
     Msg::Error("Unknown mesh element %d", elementTag);
-    GMSH_ERROR(2);
+    throw 2;
   }
   type = e->getTypeForMSH();
   vertexTags.clear();
@@ -645,15 +675,15 @@ void gmshModelGetMeshElement(const int elementTag, int &type,
     MVertex *v = e->getVertex(i);
     if(!v){
       Msg::Error("Unknown mesh vertex in element %d", elementTag);
-      GMSH_ERROR(2);
+      throw 2;
     }
     vertexTags.push_back(v->getNum());
   }
 }
 
-void gmshModelSetMeshSize(const vector_pair &dimTags, const double size)
+void gmsh::model::mesh::setSize(const vector_pair &dimTags, const double size)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   for(unsigned int i = 0; i < dimTags.size(); i++){
     int dim = dimTags[i].first, tag = dimTags[i].second;
     if(dim == 0){
@@ -663,14 +693,15 @@ void gmshModelSetMeshSize(const vector_pair &dimTags, const double size)
   }
 }
 
-void gmshModelSetTransfiniteLine(const int tag, const int numVertices,
-                                 const std::string &type, const double coef)
+void gmsh::model::mesh::setTransfiniteLine(const int tag, const int numVertices,
+                                           const std::string &type,
+                                           const double coef)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   GEdge *ge = GModel::current()->getEdgeByTag(tag);
   if(!ge){
     Msg::Error("%s does not exist", _entityName(1, tag).c_str());
-    GMSH_ERROR(2);
+    throw 2;
   }
   ge->meshAttributes.method = MESH_TRANSFINITE;
   ge->meshAttributes.nbPointsTransfinite = numVertices;
@@ -683,15 +714,15 @@ void gmshModelSetTransfiniteLine(const int tag, const int numVertices,
   if(coef < 0) ge->meshAttributes.typeTransfinite *= -1;
 }
 
-void gmshModelSetTransfiniteSurface(const int tag,
-                                    const std::string &arrangement,
-                                    const std::vector<int> &cornerTags)
+void gmsh::model::mesh::setTransfiniteSurface(const int tag,
+                                              const std::string &arrangement,
+                                              const std::vector<int> &cornerTags)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   GFace *gf = GModel::current()->getFaceByTag(tag);
   if(!gf){
     Msg::Error("%s does not exist", _entityName(2, tag).c_str());
-    GMSH_ERROR(2);
+    throw 2;
   }
   gf->meshAttributes.method = MESH_TRANSFINITE;
   gf->meshAttributes.transfiniteArrangement =
@@ -710,14 +741,14 @@ void gmshModelSetTransfiniteSurface(const int tag,
   }
 }
 
-void gmshModelSetTransfiniteVolume(const int tag,
-                                   const std::vector<int> &cornerTags)
+void gmsh::model::mesh::setTransfiniteVolume(const int tag,
+                                             const std::vector<int> &cornerTags)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   GRegion *gr = GModel::current()->getRegionByTag(tag);
   if(!gr){
     Msg::Error("%s does not exist", _entityName(3, tag).c_str());
-    GMSH_ERROR(2);
+    throw 2;
   }
   gr->meshAttributes.method = MESH_TRANSFINITE;
   if(cornerTags.empty() || cornerTags.size() == 6 || cornerTags.size() == 8){
@@ -729,39 +760,39 @@ void gmshModelSetTransfiniteVolume(const int tag,
   }
 }
 
-void gmshModelSetRecombine(const int dim, const int tag)
+void gmsh::model::mesh::setRecombine(const int dim, const int tag)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
-  if(dim != 2){ GMSH_ERROR(2); }
+  if(!_isInitialized()){ throw -1; }
+  if(dim != 2){ throw 2; }
   GFace *gf = GModel::current()->getFaceByTag(tag);
   if(!gf){
     Msg::Error("%s does not exist", _entityName(dim, tag).c_str());
-    GMSH_ERROR(2);
+    throw 2;
   }
   gf->meshAttributes.recombine = 1;
   gf->meshAttributes.recombineAngle = 45.;
 }
 
-void gmshModelSetSmoothing(const int dim, const int tag, const int val)
+void gmsh::model::mesh::setSmoothing(const int dim, const int tag, const int val)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
-  if(dim != 2){ GMSH_ERROR(2); }
+  if(!_isInitialized()){ throw -1; }
+  if(dim != 2){ throw 2; }
   GFace *gf = GModel::current()->getFaceByTag(tag);
   if(!gf){
     Msg::Error("%s does not exist", _entityName(dim, tag).c_str());
-    GMSH_ERROR(2);
+    throw 2;
   }
   gf->meshAttributes.transfiniteSmoothing = val;
 }
 
-void gmshModelSetReverseMesh(const int dim, const int tag, const bool val)
+void gmsh::model::mesh::setReverse(const int dim, const int tag, const bool val)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   if(dim == 1){
     GEdge *ge = GModel::current()->getEdgeByTag(tag);
     if(!ge){
       Msg::Error("%s does not exist", _entityName(dim, tag).c_str());
-      GMSH_ERROR(2);
+      throw 2;
     }
     ge->meshAttributes.reverseMesh = val;
   }
@@ -769,28 +800,28 @@ void gmshModelSetReverseMesh(const int dim, const int tag, const bool val)
     GFace *gf = GModel::current()->getFaceByTag(tag);
     if(!gf){
       Msg::Error("%s does not exist", _entityName(dim, tag).c_str());
-      GMSH_ERROR(2);
+      throw 2;
     }
     gf->meshAttributes.reverseMesh = val;
   }
 }
 
-void gmshModelEmbed(const int dim, const std::vector<int> &tags,
-                    const int inDim, const int inTag)
+void gmsh::model::mesh::embed(const int dim, const std::vector<int> &tags,
+                              const int inDim, const int inTag)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   if(inDim == 2){
     GFace *gf = GModel::current()->getFaceByTag(inTag);
     if(!gf){
       Msg::Error("%s does not exist", _entityName(2, inTag).c_str());
-      GMSH_ERROR(2);
+      throw 2;
     }
     for(unsigned int i = 0; i < tags.size(); i++){
       if(dim == 0){
         GVertex *gv = GModel::current()->getVertexByTag(tags[i]);
         if(!gv){
           Msg::Error("%s does not exist", _entityName(0, tags[i]).c_str());
-          GMSH_ERROR(2);
+          throw 2;
         }
         gf->addEmbeddedVertex(gv);
       }
@@ -798,7 +829,7 @@ void gmshModelEmbed(const int dim, const std::vector<int> &tags,
         GEdge *ge = GModel::current()->getEdgeByTag(tags[i]);
         if(!ge){
           Msg::Error("%s does not exist", _entityName(1, tags[i]).c_str());
-          GMSH_ERROR(2);
+          throw 2;
         }
         gf->addEmbeddedEdge(ge);
       }
@@ -808,14 +839,14 @@ void gmshModelEmbed(const int dim, const std::vector<int> &tags,
     GRegion *gr = GModel::current()->getRegionByTag(inTag);
     if(!gr){
       Msg::Error("%s does not exist", _entityName(3, inTag).c_str());
-      GMSH_ERROR(2);
+      throw 2;
     }
     for(unsigned int i = 0; i < tags.size(); i++){
       if(dim == 0){
         GVertex *gv = GModel::current()->getVertexByTag(tags[i]);
         if(!gv){
           Msg::Error("%s does not exist", _entityName(0, tags[i]).c_str());
-          GMSH_ERROR(2);
+          throw 2;
         }
         gr->addEmbeddedVertex(gv);
       }
@@ -823,7 +854,7 @@ void gmshModelEmbed(const int dim, const std::vector<int> &tags,
         GEdge *ge = GModel::current()->getEdgeByTag(tags[i]);
         if(!ge){
           Msg::Error("%s does not exist", _entityName(1, tags[i]).c_str());
-          GMSH_ERROR(2);
+          throw 2;
         }
         gr->addEmbeddedEdge(ge);
       }
@@ -831,7 +862,7 @@ void gmshModelEmbed(const int dim, const std::vector<int> &tags,
         GFace *gf = GModel::current()->getFaceByTag(tags[i]);
         if(!gf){
           Msg::Error("%s does not exist", _entityName(2, tags[i]).c_str());
-          GMSH_ERROR(2);
+          throw 2;
         }
         gr->addEmbeddedFace(gf);
       }
@@ -839,138 +870,276 @@ void gmshModelEmbed(const int dim, const std::vector<int> &tags,
   }
 }
 
-// gmshModelGeo
+// gmsh::model::mesh::field
+
+int gmsh::model::mesh::field::add(const std::string &type, const int tag)
+{
+  if(!_isInitialized()){ throw -1; }
+  int outTag = tag;
+#if defined(HAVE_MESH)
+  if(outTag < 0){
+    outTag = GModel::current()->getFields()->newId();
+  }
+  if(!GModel::current()->getFields()->newField(tag, type)){
+    Msg::Error("Cannot add Field %i of type '%s'", tag, type.c_str());
+    throw 1;
+  }
+#else
+  Msg::Error("Fields require the mesh module");
+  throw -1;
+#endif
+  return outTag;
+}
+
+void gmsh::model::mesh::field::remove(const int tag)
+{
+  if(!_isInitialized()){ throw -1; }
+#if defined(HAVE_MESH)
+  GModel::current()->getFields()->deleteField(tag);
+#else
+  Msg::Error("Fields require the mesh module");
+  throw -1;
+#endif
+}
+
+#if defined(HAVE_MESH)
+static FieldOption *_getFieldOption(const int tag, const std::string &option)
+{
+  Field *field = GModel::current()->getFields()->get(tag);
+  if(!field){
+    Msg::Error("No field with id %i", tag);
+    return 0;
+  }
+  FieldOption *o = field->options[option];
+  if(!o){
+    Msg::Error("Unknown option '%s' in field %i of type '%s'", option.c_str(),
+               tag, field->getName());
+    return 0;
+  }
+  return o;
+}
+#endif
+
+void gmsh::model::mesh::field::setNumber(const int tag, const std::string &option,
+                                         const double value)
+{
+  if(!_isInitialized()){ throw -1; }
+#if defined(HAVE_MESH)
+  FieldOption *o = _getFieldOption(tag, option);
+  if(!o){ throw 1; }
+  try { o->numericalValue(value); }
+  catch(...){
+    Msg::Error("Cannot set numerical value to option '%s' in field %i",
+               option.c_str(), tag);
+    throw 1;
+  }
+#else
+  Msg::Error("Fields require the mesh module");
+  throw -1;
+#endif
+}
+
+void gmsh::model::mesh::field::setString(const int tag, const std::string &option,
+                                         const std::string &value)
+{
+  if(!_isInitialized()){ throw -1; }
+#if defined(HAVE_MESH)
+  FieldOption *o = _getFieldOption(tag, option);
+  if(!o){ throw 1; }
+  try { o->string(value); }
+  catch(...){
+    Msg::Error("Cannot set string value to option '%s' in field %i",
+               option.c_str(), tag);
+    throw 1;
+  }
+#else
+  Msg::Error("Fields require the mesh module");
+  throw -1;
+#endif
+}
+
+void gmsh::model::mesh::field::setNumbers(const int tag, const std::string &option,
+                                          const std::vector<double> &value)
+{
+  if(!_isInitialized()){ throw -1; }
+#if defined(HAVE_MESH)
+  FieldOption *o = _getFieldOption(tag, option);
+  if(!o){ throw 1; }
+  try {
+    if(o->getType() == FIELD_OPTION_LIST) {
+      std::list<int> vl;
+      for(unsigned int i = 0; i < value.size(); i++)
+        vl.push_back((int)value[i]);
+      o->list(vl);
+    }
+    else{
+      std::list<double> vl;
+      for(unsigned int i = 0; i < value.size(); i++)
+        vl.push_back(value[i]);
+      o->listdouble(vl);
+    }
+  }
+  catch(...){
+    Msg::Error("Cannot set numeric values to option '%s' in field %i",
+               option.c_str(), tag);
+    throw 1;
+  }
+#else
+  Msg::Error("Fields require the mesh module");
+  throw -1;
+#endif
+}
+
+void gmsh::model::mesh::field::setAsBackground(const int tag)
+{
+  if(!_isInitialized()){ throw -1; }
+#if defined(HAVE_MESH)
+  GModel::current()->getFields()->setBackgroundFieldId(tag);
+#else
+  Msg::Error("Fields require the mesh module");
+  throw -1;
+#endif
+}
+
+// gmsh::model::geo
 
-int gmshModelGeoAddPoint(const double x, const double y, const double z,
-                         const double meshSize, const int tag)
+int gmsh::model::geo::addPoint(const double x, const double y, const double z,
+                               const double meshSize, const int tag)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   int outTag = tag;
   double xx = CTX::instance()->geom.scalingFactor * x;
   double yy = CTX::instance()->geom.scalingFactor * y;
   double zz = CTX::instance()->geom.scalingFactor * z;
   double lc = CTX::instance()->geom.scalingFactor * meshSize;
   if(!GModel::current()->getGEOInternals()->addVertex(outTag, xx, yy, zz, lc)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelGeoAddLine(const int startTag, const int endTag, const int tag)
+int gmsh::model::geo::addLine(const int startTag, const int endTag, const int tag)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   int outTag = tag;
   if(!GModel::current()->getGEOInternals()->addLine(outTag, startTag, endTag)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelGeoAddCircleArc(const int startTag, const int centerTag,
-                             const int endTag, const int tag, const double nx,
-                             const double ny, const double nz)
+int gmsh::model::geo::addCircleArc(const int startTag, const int centerTag,
+                                   const int endTag, const int tag, const double nx,
+                                   const double ny, const double nz)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   int outTag = tag;
   if(!GModel::current()->getGEOInternals()->addCircleArc
      (outTag, startTag, centerTag, endTag, nx, ny, nz)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelGeoAddEllipseArc(const int startTag, const int centerTag,
-                              const int majorTag, const int endTag,
-                              const int tag, const double nx, const double ny,
-                              const double nz)
+int gmsh::model::geo::addEllipseArc(const int startTag, const int centerTag,
+                                    const int majorTag, const int endTag,
+                                    const int tag, const double nx, const double ny,
+                                    const double nz)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   int outTag = tag;
   if(!GModel::current()->getGEOInternals()->addEllipseArc
      (outTag, startTag, centerTag, majorTag, endTag, nx, ny, nz)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelGeoAddSpline(const std::vector<int> &vertexTags, const int tag)
+int gmsh::model::geo::addSpline(const std::vector<int> &vertexTags,
+                                const int tag)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   int outTag = tag;
   if(!GModel::current()->getGEOInternals()->addSpline(outTag, vertexTags)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelGeoAddBSpline(const std::vector<int> &vertexTags, const int tag)
+int gmsh::model::geo::addBSpline(const std::vector<int> &vertexTags,
+                                 const int tag)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   int outTag = tag;
   if(!GModel::current()->getGEOInternals()->addBSpline(outTag, vertexTags)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelGeoAddBezier(const std::vector<int> &vertexTags, const int tag)
+int gmsh::model::geo::addBezier(const std::vector<int> &vertexTags,
+                                const int tag)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   int outTag = tag;
   if(!GModel::current()->getGEOInternals()->addBezier(outTag, vertexTags)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelGeoAddLineLoop(const std::vector<int> &edgeTags, const int tag)
+int gmsh::model::geo::addLineLoop(const std::vector<int> &edgeTags,
+                                  const int tag)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   int outTag = tag;
   if(!GModel::current()->getGEOInternals()->addLineLoop(outTag, edgeTags)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelGeoAddPlaneSurface(const std::vector<int> &wireTags, const int tag)
+int gmsh::model::geo::addPlaneSurface(const std::vector<int> &wireTags,
+                                      const int tag)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   int outTag = tag;
   if(!GModel::current()->getGEOInternals()->addPlaneSurface(outTag, wireTags)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelGeoAddSurfaceFilling(const std::vector<int> &wireTags, const int tag,
-                                  const int sphereCenterTag)
+int gmsh::model::geo::addSurfaceFilling(const std::vector<int> &wireTags,
+                                        const int tag,
+                                        const int sphereCenterTag)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   int outTag = tag;
   if(!GModel::current()->getGEOInternals()->addSurfaceFilling
      (outTag, wireTags, sphereCenterTag)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelGeoAddSurfaceLoop(const std::vector<int> &faceTags, const int tag)
+int gmsh::model::geo::addSurfaceLoop(const std::vector<int> &faceTags,
+                                     const int tag)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   int outTag = tag;
   if(!GModel::current()->getGEOInternals()->addSurfaceLoop(outTag, faceTags)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelGeoAddVolume(const std::vector<int> &shellTags, const int tag)
+int gmsh::model::geo::addVolume(const std::vector<int> &shellTags, const int tag)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   int outTag = tag;
   if(!GModel::current()->getGEOInternals()->addVolume(outTag, shellTags)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
@@ -997,128 +1166,136 @@ static ExtrudeParams *_getExtrudeParams(const std::vector<int> &numElements,
   return e;
 }
 
-void gmshModelGeoExtrude(const vector_pair &dimTags,
-                         const double dx, const double dy, const double dz,
-                         vector_pair &outDimTags,
-                         const std::vector<int> &numElements,
-                         const std::vector<double> &heights,
-                         const bool recombine)
+void gmsh::model::geo::extrude(const vector_pair &dimTags,
+                               const double dx, const double dy, const double dz,
+                               vector_pair &outDimTags,
+                               const std::vector<int> &numElements,
+                               const std::vector<double> &heights,
+                               const bool recombine)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   outDimTags.clear();
   if(!GModel::current()->getGEOInternals()->extrude
      (dimTags, dx, dy, dz, outDimTags,
       _getExtrudeParams(numElements, heights, recombine))){
-    GMSH_ERROR(1);
+    throw 1;
   }
 }
 
-void gmshModelGeoRevolve(const vector_pair &dimTags,
-                         const double x, const double y, const double z,
-                         const double ax, const double ay, const double az,
-                         const double angle,
-                         vector_pair &outDimTags,
-                         const std::vector<int> &numElements,
-                         const std::vector<double> &heights,
-                         const bool recombine)
+void gmsh::model::geo::revolve(const vector_pair &dimTags,
+                               const double x, const double y, const double z,
+                               const double ax, const double ay, const double az,
+                               const double angle,
+                               vector_pair &outDimTags,
+                               const std::vector<int> &numElements,
+                               const std::vector<double> &heights,
+                               const bool recombine)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   outDimTags.clear();
   if(!GModel::current()->getGEOInternals()->revolve
      (dimTags, x, y, z, ax, ay, az, angle, outDimTags,
       _getExtrudeParams(numElements, heights, recombine))){
-    GMSH_ERROR(1);
+    throw 1;
   }
 }
 
-void gmshModelGeoTwist(const vector_pair &dimTags,
-                       const double x, const double y, const double z,
-                       const double dx, const double dy, const double dz,
-                       const double ax, const double ay, const double az,
-                       const double angle,
-                       vector_pair &outDimTags,
-                       const std::vector<int> &numElements,
-                       const std::vector<double> &heights,
-                       const bool recombine)
+void gmsh::model::geo::twist(const vector_pair &dimTags,
+                             const double x, const double y, const double z,
+                             const double dx, const double dy, const double dz,
+                             const double ax, const double ay, const double az,
+                             const double angle,
+                             vector_pair &outDimTags,
+                             const std::vector<int> &numElements,
+                             const std::vector<double> &heights,
+                             const bool recombine)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   outDimTags.clear();
   if(!GModel::current()->getGEOInternals()->twist
      (dimTags, x, y, z, dx, dy, dz, ax, ay, az, angle, outDimTags,
       _getExtrudeParams(numElements, heights, recombine))){
-    GMSH_ERROR(1);
+    throw 1;
   }
 }
 
-void gmshModelGeoTranslate(const vector_pair &dimTags, const double dx,
-                           const double dy, const double dz)
+void gmsh::model::geo::translate(const vector_pair &dimTags, const double dx,
+                                 const double dy, const double dz)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   if(!GModel::current()->getGEOInternals()->translate(dimTags, dx, dy, dz)){
-    GMSH_ERROR(1);
+    throw 1;
   }
 }
 
-void gmshModelGeoRotate(const vector_pair &dimTags, const double x,
-                        const double y, const double z, const double ax,
-                        const double ay, const double az, const double angle)
+void gmsh::model::geo::rotate(const vector_pair &dimTags, const double x,
+                              const double y, const double z, const double ax,
+                              const double ay, const double az, const double angle)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   if(!GModel::current()->getGEOInternals()->rotate
      (dimTags, x, y, z, ax, ay, az, angle)){
-    GMSH_ERROR(1);
+    throw 1;
   }
 }
 
-void gmshModelGeoDilate(const vector_pair &dimTags, const double x,
-                        const double y, const double z, const double a,
-                        const double b, const double c)
+void gmsh::model::geo::dilate(const vector_pair &dimTags, const double x,
+                              const double y, const double z, const double a,
+                              const double b, const double c)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   if(!GModel::current()->getGEOInternals()->dilate
      (dimTags, x, y, z, a, b, c)){
-    GMSH_ERROR(1);
+    throw 1;
   }
 }
 
-void gmshModelGeoSymmetry(const vector_pair &dimTags, const double a,
-                          const double b, const double c, const double d)
+void gmsh::model::geo::symmetry(const vector_pair &dimTags, const double a,
+                                const double b, const double c, const double d)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   if(!GModel::current()->getGEOInternals()->symmetry
      (dimTags, a, b, c, d)){
-    GMSH_ERROR(1);
+    throw 1;
   }
 }
 
-void gmshModelGeoCopy(const vector_pair &dimTags, vector_pair &outDimTags)
+void gmsh::model::geo::copy(const vector_pair &dimTags, vector_pair &outDimTags)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   outDimTags.clear();
   if(!GModel::current()->getGEOInternals()->copy(dimTags, outDimTags)){
-    GMSH_ERROR(1);
+    throw 1;
   }
 }
 
-void gmshModelGeoRemove(const vector_pair &dimTags, const bool recursive)
+void gmsh::model::geo::remove(const vector_pair &dimTags, const bool recursive)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   if(!GModel::current()->getGEOInternals()->remove(dimTags, recursive)){
-    GMSH_ERROR(1);
+    throw 1;
   }
 }
 
-void gmshModelGeoRemoveAllDuplicates()
+void gmsh::model::geo::removeAllDuplicates()
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   GModel::current()->getGEOInternals()->removeAllDuplicates();
 }
 
-void gmshModelGeoSetTransfiniteLine(const int tag, const int nPoints,
-                                    const std::string &type,
-                                    const double coef)
+void gmsh::model::geo::synchronize()
+{
+  if(!_isInitialized()){ throw -1; }
+  GModel::current()->getGEOInternals()->synchronize(GModel::current());
+}
+
+// gmsh::model::geo::mesh
+
+void gmsh::model::geo::mesh::setTransfiniteLine(const int tag, const int nPoints,
+                                                const std::string &type,
+                                                const double coef)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   int t =
     (type == "Progression" || type == "Power") ? 1 :
     (type == "Bump") ? 2 :
@@ -1129,11 +1306,11 @@ void gmshModelGeoSetTransfiniteLine(const int tag, const int nPoints,
   GModel::current()->getGEOInternals()->setTransfiniteLine(tag, nPoints, t, c);
 }
 
-void gmshModelGeoSetTransfiniteSurface(const int tag,
-                                       const std::string &arrangement,
-                                       const std::vector<int> &cornerTags)
+void gmsh::model::geo::mesh::setTransfiniteSurface(const int tag,
+                                                   const std::string &arrangement,
+                                                   const std::vector<int> &cornerTags)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   int t =
     (arrangement == "Right") ? 1 :
     (arrangement == "Left") ? -1 :
@@ -1144,448 +1321,445 @@ void gmshModelGeoSetTransfiniteSurface(const int tag,
   GModel::current()->getGEOInternals()->setTransfiniteSurface(tag, t, cornerTags);
 }
 
-void gmshModelGeoSetTransfiniteVolume(const int tag,
-                                      const std::vector<int> &cornerTags)
+void gmsh::model::geo::mesh::setTransfiniteVolume(const int tag,
+                                                  const std::vector<int> &cornerTags)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   GModel::current()->getGEOInternals()->setTransfiniteVolume(tag, cornerTags);
 }
 
-void gmshModelGeoSetRecombine(const int dim, const int tag, const double angle)
+void gmsh::model::geo::mesh::setRecombine(const int dim, const int tag,
+                                          const double angle)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   GModel::current()->getGEOInternals()->setRecombine(dim, tag, angle);
 }
 
-void gmshModelGeoSetSmoothing(const int dim, const int tag, const int val)
+void gmsh::model::geo::mesh::setSmoothing(const int dim, const int tag, const int val)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
-  if(dim != 2){ GMSH_ERROR(2); }
+  if(!_isInitialized()){ throw -1; }
+  if(dim != 2){ throw 2; }
   GModel::current()->getGEOInternals()->setSmoothing(tag, val);
 }
 
-void gmshModelGeoSetReverseMesh(const int dim, const int tag, const bool val)
+void gmsh::model::geo::mesh::setReverse(const int dim, const int tag, const bool val)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   GModel::current()->getGEOInternals()->setReverseMesh(dim, tag, val);
 }
 
-void gmshModelGeoSetMeshSize(const vector_pair &dimTags, const double size)
+void gmsh::model::geo::mesh::setSize(const vector_pair &dimTags, const double size)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   for(unsigned int i = 0; i < dimTags.size(); i++){
     int dim = dimTags[i].first, tag = dimTags[i].second;
     GModel::current()->getGEOInternals()->setMeshSize(dim, tag, size);
   }
 }
 
-void gmshModelGeoSynchronize()
-{
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
-  GModel::current()->getGEOInternals()->synchronize(GModel::current());
-}
-
-// gmshModelOcc
+// gmsh::model::occ
 
 static void _createOcc()
 {
   if(!GModel::current()->getOCCInternals()) GModel::current()->createOCCInternals();
 }
 
-int gmshModelOccAddPoint(const double x, const double y, const double z,
-                         const double meshSize, const int tag)
+int gmsh::model::occ::addPoint(const double x, const double y, const double z,
+                               const double meshSize, const int tag)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   int outTag = tag;
   if(!GModel::current()->getOCCInternals()->addVertex(outTag, x, y, z, meshSize)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelOccAddLine(const int startTag, const int endTag, const int tag)
+int gmsh::model::occ::addLine(const int startTag, const int endTag, const int tag)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   int outTag = tag;
   if(!GModel::current()->getOCCInternals()->addLine(outTag, startTag, endTag)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelOccAddCircleArc(const int startTag, const int centerTag,
-                             const int endTag, const int tag)
+int gmsh::model::occ::addCircleArc(const int startTag, const int centerTag,
+                                   const int endTag, const int tag)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   int outTag = tag;
   if(!GModel::current()->getOCCInternals()->addCircleArc
      (outTag, startTag, centerTag, endTag)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelOccAddCircle(const double x, const double y, const double z,
-                          const double r, const int tag,
-                          const double angle1, const double angle2)
+int gmsh::model::occ::addCircle(const double x, const double y, const double z,
+                                const double r, const int tag,
+                                const double angle1, const double angle2)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   int outTag = tag;
   if(!GModel::current()->getOCCInternals()->addCircle
      (outTag, x, y, z, r, angle1, angle2)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelOccAddEllipseArc(const int startTag, const int centerTag,
-                              const int endTag, const int tag)
+int gmsh::model::occ::addEllipseArc(const int startTag, const int centerTag,
+                                    const int endTag, const int tag)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   int outTag = tag;
   if(!GModel::current()->getOCCInternals()->addEllipseArc
      (outTag, startTag, centerTag, endTag)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelOccAddEllipse(const double x, const double y, const double z,
-                           const double r1, const double r2,
-                           const int tag,
-                           const double angle1, const double angle2)
+int gmsh::model::occ::addEllipse(const double x, const double y, const double z,
+                                 const double r1, const double r2,
+                                 const int tag,
+                                 const double angle1, const double angle2)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   int outTag = tag;
   if(!GModel::current()->getOCCInternals()->addEllipse
      (outTag, x, y, z, r1, r2, angle1, angle2)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelOccAddSpline(const std::vector<int> &vertexTags, const int tag)
+int gmsh::model::occ::addSpline(const std::vector<int> &vertexTags, const int tag)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   int outTag = tag;
   if(!GModel::current()->getOCCInternals()->addSpline(outTag, vertexTags)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelOccAddBezier(const std::vector<int> &vertexTags, const int tag)
+int gmsh::model::occ::addBezier(const std::vector<int> &vertexTags, const int tag)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   int outTag = tag;
   if(!GModel::current()->getOCCInternals()->addBezier(outTag, vertexTags)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelOccAddBSpline(const std::vector<int> &vertexTags, const int tag)
+int gmsh::model::occ::addBSpline(const std::vector<int> &vertexTags, const int tag)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   int outTag = tag;
   if(!GModel::current()->getOCCInternals()->addBSpline(outTag, vertexTags)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelOccAddWire(const std::vector<int> &edgeTags, const int tag,
-                        const bool checkClosed)
+int gmsh::model::occ::addWire(const std::vector<int> &edgeTags, const int tag,
+                              const bool checkClosed)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   int outTag = tag;
   if(!GModel::current()->getOCCInternals()->addWire
      (outTag, edgeTags, checkClosed)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelOccAddLineLoop(const std::vector<int> &edgeTags, const int tag)
+int gmsh::model::occ::addLineLoop(const std::vector<int> &edgeTags, const int tag)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   int outTag = tag;
   if(!GModel::current()->getOCCInternals()->addLineLoop(outTag, edgeTags)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelOccAddRectangle(const double x, const double y, const double z,
-                             const double dx, const double dy, const int tag,
-                             const double roundedRadius)
+int gmsh::model::occ::addRectangle(const double x, const double y, const double z,
+                                   const double dx, const double dy, const int tag,
+                                   const double roundedRadius)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   int outTag = tag;
   if(!GModel::current()->getOCCInternals()->addRectangle
      (outTag, x, y, z, dx, dy, roundedRadius)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelOccAddDisk(const double xc, const double yc, const double zc,
-                        const double rx, const double ry, const int tag)
+int gmsh::model::occ::addDisk(const double xc, const double yc, const double zc,
+                              const double rx, const double ry, const int tag)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   int outTag = tag;
   if(!GModel::current()->getOCCInternals()->addDisk
      (outTag, xc, yc, zc, rx, ry)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelOccAddPlaneSurface(const std::vector<int> &wireTags, const int tag)
+int gmsh::model::occ::addPlaneSurface(const std::vector<int> &wireTags,
+                                      const int tag)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   int outTag = tag;
   if(!GModel::current()->getOCCInternals()->addPlaneSurface(outTag, wireTags)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelOccAddSurfaceFilling(const int wireTag, const int tag)
+int gmsh::model::occ::addSurfaceFilling(const int wireTag, const int tag)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   int outTag = tag;
   if(!GModel::current()->getOCCInternals()->addSurfaceFilling(outTag, wireTag)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelOccAddSurfaceLoop(const std::vector<int> &faceTags, const int tag)
+int gmsh::model::occ::addSurfaceLoop(const std::vector<int> &faceTags,
+                                     const int tag)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   int outTag = tag;
   if(!GModel::current()->getOCCInternals()->addSurfaceLoop(outTag, faceTags)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelOccAddVolume(const std::vector<int> &shellTags, const int tag)
+int gmsh::model::occ::addVolume(const std::vector<int> &shellTags, const int tag)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   int outTag = tag;
   if(!GModel::current()->getOCCInternals()->addVolume(outTag, shellTags)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelOccAddSphere(const double xc, const double yc, const double zc,
-                          const double radius, const int tag,
-                          const double angle1, const double angle2,
-                          const double angle3)
+int gmsh::model::occ::addSphere(const double xc, const double yc, const double zc,
+                                const double radius, const int tag,
+                                const double angle1, const double angle2,
+                                const double angle3)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   int outTag = tag;
   if(!GModel::current()->getOCCInternals()->addSphere
      (outTag, xc, yc, zc, radius, angle1, angle2, angle3)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelOccAddBox(const double x, const double y, const double z,
-                       const double dx, const double dy, const double dz,
-                       const int tag)
+int gmsh::model::occ::addBox(const double x, const double y, const double z,
+                             const double dx, const double dy, const double dz,
+                             const int tag)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   int outTag = tag;
   if(!GModel::current()->getOCCInternals()->addBox
      (outTag, x, y, z, dx, dy, dz)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelOccAddCylinder(const double x, const double y, const double z,
-                            const double dx, const double dy, const double dz,
-                            const double r, const int tag, const double angle)
+int gmsh::model::occ::addCylinder(const double x, const double y, const double z,
+                                  const double dx, const double dy, const double dz,
+                                  const double r, const int tag, const double angle)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   int outTag = tag;
   if(!GModel::current()->getOCCInternals()->addCylinder
      (outTag, x, y, z, dx, dy, dz, r, angle)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelOccAddCone(const double x, const double y, const double z,
-                        const double dx, const double dy, const double dz,
-                        const double r1, const double r2, const int tag,
-                        const double angle)
+int gmsh::model::occ::addCone(const double x, const double y, const double z,
+                              const double dx, const double dy, const double dz,
+                              const double r1, const double r2, const int tag,
+                              const double angle)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   int outTag = tag;
   if(!GModel::current()->getOCCInternals()->addCone
      (outTag, x, y, z, dx, dy, dz, r1, r2, angle)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelOccAddWedge(const double x, const double y, const double z,
-                         const double dx, const double dy, const double dz,
-                         const int tag, const double ltx)
+int gmsh::model::occ::addWedge(const double x, const double y, const double z,
+                               const double dx, const double dy, const double dz,
+                               const int tag, const double ltx)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   int outTag = tag;
   if(!GModel::current()->getOCCInternals()->addWedge
      (outTag, x, y, z, dx, dy, dz, ltx)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelOccAddTorus(const double x, const double y, const double z,
-                         const double r1, const double r2, const int tag,
-                         const double angle)
+int gmsh::model::occ::addTorus(const double x, const double y, const double z,
+                               const double r1, const double r2, const int tag,
+                               const double angle)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   int outTag = tag;
   if(!GModel::current()->getOCCInternals()->addTorus
      (outTag, x, y, z, r1, r2, angle)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelOccAddThruSections(const std::vector<int> &wireTags,
-                                vector_pair &outDimTags,
-                                const int tag, const bool makeSolid,
-                                const bool makeRuled)
+int gmsh::model::occ::addThruSections(const std::vector<int> &wireTags,
+                                      vector_pair &outDimTags,
+                                      const int tag, const bool makeSolid,
+                                      const bool makeRuled)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   int outTag = tag;
   outDimTags.clear();
   if(!GModel::current()->getOCCInternals()->addThruSections
      (outTag, wireTags, makeSolid, makeRuled, outDimTags)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int addThickSolid(const int solidTag,
-                  const std::vector<int> &excludeFaceTags,
-                  const double offset, vector_pair &outDimTags,
-                  const int tag)
+int gmsh::model::occ::addThickSolid(const int solidTag,
+                                    const std::vector<int> &excludeFaceTags,
+                                    const double offset, vector_pair &outDimTags,
+                                    const int tag)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   int outTag = tag;
   outDimTags.clear();
   if(!GModel::current()->getOCCInternals()->addThickSolid
      (outTag, solidTag, excludeFaceTags, offset, outDimTags)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-void gmshModelOccExtrude(const vector_pair &dimTags,
-                         const double dx, const double dy, const double dz,
-                         vector_pair &outDimTags,
-                         const std::vector<int> &numElements,
-                         const std::vector<double> &heights,
-                         const bool recombine)
+void gmsh::model::occ::extrude(const vector_pair &dimTags,
+                               const double dx, const double dy, const double dz,
+                               vector_pair &outDimTags,
+                               const std::vector<int> &numElements,
+                               const std::vector<double> &heights,
+                               const bool recombine)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   outDimTags.clear();
   if(!GModel::current()->getOCCInternals()->extrude
     (dimTags, dx, dy, dz, outDimTags,
      _getExtrudeParams(numElements, heights, recombine))){
-    GMSH_ERROR(1);
+    throw 1;
   }
 }
 
-void gmshModelOccRevolve(const vector_pair &dimTags,
-                         const double x, const double y, const double z,
-                         const double ax, const double ay, const double az,
-                         const double angle, vector_pair &outDimTags,
-                         const std::vector<int> &numElements,
-                         const std::vector<double> &heights,
-                         const bool recombine)
+void gmsh::model::occ::revolve(const vector_pair &dimTags,
+                               const double x, const double y, const double z,
+                               const double ax, const double ay, const double az,
+                               const double angle, vector_pair &outDimTags,
+                               const std::vector<int> &numElements,
+                               const std::vector<double> &heights,
+                               const bool recombine)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   outDimTags.clear();
   if(!GModel::current()->getOCCInternals()->revolve
      (dimTags, x, y, z, ax, ay, az, angle, outDimTags,
       _getExtrudeParams(numElements, heights, recombine))){
-    GMSH_ERROR(1);
+    throw 1;
   }
 }
 
-void gmshModelOccAddPipe(const vector_pair &dimTags, const int wireTag,
-                         vector_pair &outDimTags)
+void gmsh::model::occ::addPipe(const vector_pair &dimTags, const int wireTag,
+                               vector_pair &outDimTags)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   outDimTags.clear();
   if(!GModel::current()->getOCCInternals()->addPipe
      (dimTags, wireTag, outDimTags)){
-    GMSH_ERROR(1);
+    throw 1;
   }
 }
 
-void gmshModelOccFillet(const std::vector<int> &regionTags,
-                        const std::vector<int> &edgeTags,
-                        const double radius, vector_pair &outDimTags,
-                        const bool removeRegion)
+void gmsh::model::occ::fillet(const std::vector<int> &regionTags,
+                              const std::vector<int> &edgeTags,
+                              const double radius, vector_pair &outDimTags,
+                              const bool removeRegion)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   outDimTags.clear();
   if(!GModel::current()->getOCCInternals()->fillet
      (regionTags, edgeTags, radius, outDimTags, removeRegion)){
-    GMSH_ERROR(1);
+    throw 1;
   }
 }
 
-int gmshModelOccBooleanUnion(const vector_pair &objectDimTags,
-                             const vector_pair &toolDimTags,
-                             vector_pair &outDimTags,
-                             std::vector<vector_pair > &outDimTagsMap,
-                             const int tag,
-                             const bool removeObject,
-                             const bool removeTool)
+int gmsh::model::occ::booleanUnion(const vector_pair &objectDimTags,
+                                   const vector_pair &toolDimTags,
+                                   vector_pair &outDimTags,
+                                   std::vector<vector_pair > &outDimTagsMap,
+                                   const int tag,
+                                   const bool removeObject,
+                                   const bool removeTool)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   int outTag = tag;
   outDimTags.clear();
@@ -1593,20 +1767,20 @@ int gmshModelOccBooleanUnion(const vector_pair &objectDimTags,
   if(!GModel::current()->getOCCInternals()->booleanUnion
      (outTag, objectDimTags, toolDimTags, outDimTags, outDimTagsMap,
       removeObject, removeTool)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelOccBooleanIntersection(const vector_pair &objectDimTags,
-                                    const vector_pair &toolDimTags,
-                                    vector_pair &outDimTags,
-                                    std::vector<vector_pair> &outDimTagsMap,
-                                    const int tag,
-                                    const bool removeObject,
-                                    const bool removeTool)
+int gmsh::model::occ::booleanIntersection(const vector_pair &objectDimTags,
+                                          const vector_pair &toolDimTags,
+                                          vector_pair &outDimTags,
+                                          std::vector<vector_pair> &outDimTagsMap,
+                                          const int tag,
+                                          const bool removeObject,
+                                          const bool removeTool)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   int outTag = tag;
   outDimTags.clear();
@@ -1614,20 +1788,20 @@ int gmshModelOccBooleanIntersection(const vector_pair &objectDimTags,
   if(!GModel::current()->getOCCInternals()->booleanIntersection
      (outTag, objectDimTags, toolDimTags, outDimTags, outDimTagsMap,
       removeObject, removeTool)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelOccBooleanDifference(const vector_pair &objectDimTags,
-                                  const vector_pair &toolDimTags,
-                                  vector_pair &outDimTags,
-                                  std::vector<vector_pair> &outDimTagsMap,
-                                  const int tag,
-                                  const bool removeObject,
-                                  const bool removeTool)
+int gmsh::model::occ::booleanDifference(const vector_pair &objectDimTags,
+                                        const vector_pair &toolDimTags,
+                                        vector_pair &outDimTags,
+                                        std::vector<vector_pair> &outDimTagsMap,
+                                        const int tag,
+                                        const bool removeObject,
+                                        const bool removeTool)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   int outTag = tag;
   outDimTags.clear();
@@ -1635,20 +1809,20 @@ int gmshModelOccBooleanDifference(const vector_pair &objectDimTags,
   if(!GModel::current()->getOCCInternals()->booleanDifference
      (outTag, objectDimTags, toolDimTags, outDimTags, outDimTagsMap,
       removeObject, removeTool)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-int gmshModelOccBooleanFragments(const vector_pair &objectDimTags,
-                                 const vector_pair &toolDimTags,
-                                 vector_pair &outDimTags,
-                                 std::vector<vector_pair> &outDimTagsMap,
-                                 const int tag,
-                                 const bool removeObject,
-                                 const bool removeTool)
+int gmsh::model::occ::booleanFragments(const vector_pair &objectDimTags,
+                                       const vector_pair &toolDimTags,
+                                       vector_pair &outDimTags,
+                                       std::vector<vector_pair> &outDimTagsMap,
+                                       const int tag,
+                                       const bool removeObject,
+                                       const bool removeTool)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   int outTag = tag;
   outDimTags.clear();
@@ -1656,98 +1830,98 @@ int gmshModelOccBooleanFragments(const vector_pair &objectDimTags,
   if(!GModel::current()->getOCCInternals()->booleanFragments
      (outTag, objectDimTags, toolDimTags, outDimTags, outDimTagsMap,
       removeObject, removeTool)){
-    GMSH_ERROR(1);
+    throw 1;
   }
   return outTag;
 }
 
-void gmshModelOccTranslate(const vector_pair &dimTags, const double dx,
-                           const double dy, const double dz)
+void gmsh::model::occ::translate(const vector_pair &dimTags, const double dx,
+                                 const double dy, const double dz)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   if(!GModel::current()->getOCCInternals()->translate(dimTags, dx, dy, dz)){
-    GMSH_ERROR(1);
+    throw 1;
   }
 }
 
-void gmshModelOccRotate(const vector_pair &dimTags, const double x,
-                        const double y, const double z, const double ax,
-                        const double ay, const double az, const double angle)
+void gmsh::model::occ::rotate(const vector_pair &dimTags, const double x,
+                              const double y, const double z, const double ax,
+                              const double ay, const double az, const double angle)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   if(!GModel::current()->getOCCInternals()->rotate
      (dimTags, x, y, z, ax, ay, az, angle)){
-    GMSH_ERROR(1);
+    throw 1;
   }
 }
 
-void gmshModelOccDilate(const vector_pair &dimTags, const double x,
-                        const double y, const double z, const double a,
-                        const double b, const double c)
+void gmsh::model::occ::dilate(const vector_pair &dimTags, const double x,
+                              const double y, const double z, const double a,
+                              const double b, const double c)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   if(!GModel::current()->getOCCInternals()->dilate
      (dimTags, x, y, z, a, b, c)){
-    GMSH_ERROR(1);
+    throw 1;
   }
 }
 
-void gmshModelOccSymmetry(const vector_pair &dimTags, const double a,
-                          const double b, const double c, const double d)
+void gmsh::model::occ::symmetry(const vector_pair &dimTags, const double a,
+                                const double b, const double c, const double d)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   if(!GModel::current()->getOCCInternals()->symmetry(dimTags, a, b, c, d)){
-    GMSH_ERROR(1);
+    throw 1;
   }
 }
 
-void gmshModelOccCopy(const vector_pair &dimTags, vector_pair &outDimTags)
+void gmsh::model::occ::copy(const vector_pair &dimTags, vector_pair &outDimTags)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   outDimTags.clear();
   if(!GModel::current()->getOCCInternals()->copy(dimTags, outDimTags)){
-    GMSH_ERROR(1);
+    throw 1;
   }
 }
 
-void gmshModelOccRemove(const vector_pair &dimTags, const bool recursive)
+void gmsh::model::occ::remove(const vector_pair &dimTags, const bool recursive)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   if(!GModel::current()->getOCCInternals()->remove(dimTags, recursive)){
-    GMSH_ERROR(1);
+    throw 1;
   }
 }
 
-void gmshModelOccRemoveAllDuplicates()
+void gmsh::model::occ::removeAllDuplicates()
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   GModel::current()->getOCCInternals()->removeAllDuplicates();
 }
 
-void gmshModelOccImportShapes(const std::string &fileName,
-                              vector_pair &outDimTags,
-                              const bool highestDimOnly,
-                              const std::string &format)
+void gmsh::model::occ::importShapes(const std::string &fileName,
+                                    vector_pair &outDimTags,
+                                    const bool highestDimOnly,
+                                    const std::string &format)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   outDimTags.clear();
   if(!GModel::current()->getOCCInternals()->importShapes
      (fileName, highestDimOnly, outDimTags, format)){
-    GMSH_ERROR(1);
+    throw 1;
   }
 }
 
-void gmshModelOccSetMeshSize(const vector_pair &dimTags, const double size)
+void gmsh::model::occ::setMeshSize(const vector_pair &dimTags, const double size)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   for(unsigned int i = 0; i < dimTags.size(); i++){
     int dim = dimTags[i].first, tag = dimTags[i].second;
@@ -1755,141 +1929,295 @@ void gmshModelOccSetMeshSize(const vector_pair &dimTags, const double size)
   }
 }
 
-void gmshModelOccSynchronize()
+void gmsh::model::occ::synchronize()
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
+  if(!_isInitialized()){ throw -1; }
   _createOcc();
   GModel::current()->getOCCInternals()->synchronize(GModel::current());
 }
 
-// gmshModelField
+// gmsh::view
 
-int gmshModelFieldCreate(const std::string &type, const int tag)
+int gmsh::view::add(const std::string &name, const int tag)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
-  int outTag = tag;
-#if defined(HAVE_MESH)
-  if(outTag < 0){
-    outTag = GModel::current()->getFields()->newId();
-  }
-  if(!GModel::current()->getFields()->newField(tag, type)){
-    Msg::Error("Cannot create Field %i of type '%s'", tag, type.c_str());
-    GMSH_ERROR(1);
+  if(!_isInitialized()){ throw -1; }
+#if defined(HAVE_POST)
+  PView *view = new PView(tag);
+  view->getData()->setName(name);
+  return view->getTag();
+#else
+  Msg::Error("Views require the post-processing module");
+  throw -1;
+#endif
+}
+
+void gmsh::view::remove(const int tag)
+{
+  if(!_isInitialized()){ throw -1; }
+#if defined(HAVE_POST)
+  PView *view = PView::getViewByTag(tag);
+  if(!view){
+    Msg::Error("Unknown view with tag %d", tag);
+    throw 2;
   }
+  delete view;
 #else
-  Msg::Error("Fields require the mesh module");
-  GMSH_ERROR(-1);
+  Msg::Error("Views require the post-processing module");
+  throw -1;
 #endif
-  return outTag;
 }
 
-void gmshModelFieldDelete(const int tag)
+int gmsh::view::getIndex(const int tag)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
-#if defined(HAVE_MESH)
-  GModel::current()->getFields()->deleteField(tag);
+  if(!_isInitialized()){ throw -1; }
+#if defined(HAVE_POST)
+  PView *view = PView::getViewByTag(tag);
+  if(!view){
+    Msg::Error("Unknown view with tag %d", tag);
+    throw 2;
+  }
+  return view->getIndex();
 #else
-  Msg::Error("Fields require the mesh module");
-  GMSH_ERROR(-1);
+  Msg::Error("Views require the post-processing module");
+  throw -1;
 #endif
 }
 
-#if defined(HAVE_MESH)
-static FieldOption *_getFieldOption(const int tag, const std::string &option)
+void gmsh::view::getTags(std::vector<int> &tags)
 {
-  Field *field = GModel::current()->getFields()->get(tag);
-  if(!field){
-    Msg::Error("No field with id %i", tag);
-    return 0;
+  if(!_isInitialized()){ throw -1; }
+#if defined(HAVE_POST)
+  tags.clear();
+  for(unsigned int i = 0; i < PView::list.size(); i++)
+    tags.push_back(PView::list[i]->getTag());
+#else
+  Msg::Error("Views require the post-processing module");
+  throw -1;
+#endif
+}
+
+void gmsh::view::addModelData(const int tag, const std::string &modelName,
+                              const std::string &dataType,
+                              const std::vector<int> &tags,
+                              const std::vector<std::vector<double> > &data,
+                              const int step, const int time,
+                              const int numComponents, const int partition)
+{
+  if(!_isInitialized()){ throw -1; }
+#if defined(HAVE_POST)
+  PView *view = PView::getViewByTag(tag);
+  if(!view){
+    Msg::Error("Unknown view with tag %d", tag);
+    throw 2;
+  }
+  GModel *model = GModel::current();
+  if(modelName.size()){
+    model = GModel::findByName(modelName);
+    if(!model){
+      Msg::Error("Unknown model '%s'", modelName.c_str());
+      throw 2;
+    }
   }
-  FieldOption *o = field->options[option];
-  if(!o){
-    Msg::Error("Unknown option '%s' in field %i of type '%s'", option.c_str(),
-               tag, field->getName());
-    return 0;
+  if(tags.size() != data.size()){
+    Msg::Error("Incompatible number of tags and data");
+    throw 2;
+  }
+  PViewDataGModel *d = dynamic_cast<PViewDataGModel*>(view->getData());
+  if(!d){ // change the view type
+    std::string name = view->getData()->getName();
+    delete view->getData();
+    PViewDataGModel::DataType type;
+    if(dataType == "NodeData")
+      type = PViewDataGModel::NodeData;
+    else if(dataType == "ElementData")
+      type = PViewDataGModel::ElementData;
+    else if(dataType == "ElementNodeData")
+      type = PViewDataGModel::ElementNodeData;
+    else if(dataType == "Beam")
+      type = PViewDataGModel::BeamData;
+    else{
+      Msg::Error("Unknown type of view to add '%s'", dataType.c_str());
+      throw 2;
+    }
+    d = new PViewDataGModel(type);
+    d->setName(name);
+    d->setFileName(name + ".msh");
+    view->setData(d);
+  }
+  d->addData(model, tags, data, step, time, partition, numComponents);
+  if(view->getOptions()->adaptVisualizationGrid)
+    d->initAdaptiveData(view->getOptions()->timeStep,
+                        view->getOptions()->maxRecursionLevel,
+                        view->getOptions()->targetError);
+#else
+  Msg::Error("Views require the post-processing module");
+  throw -1;
+#endif
+}
+
+void gmsh::view::addListData(const int tag, const std::string &type,
+                             const int numEle, const std::vector<double> &data)
+{
+  if(!_isInitialized()){ throw -1; }
+#if defined(HAVE_POST)
+  PView *view = PView::getViewByTag(tag);
+  if(!view){
+    Msg::Error("Unknown view with tag %d", tag);
+    throw 2;
+  }
+  PViewDataList *d = dynamic_cast<PViewDataList*>(view->getData());
+  if(!d){ // change the view type
+    std::string name = view->getData()->getName();
+    delete view->getData();
+    d = new PViewDataList();
+    d->setName(name);
+    d->setFileName(name + ".pos");
+    view->setData(d);
+  }
+  const char *types[] = {"SP", "VP", "TP", "SL", "VL", "TL", "ST", "VT", "TT",
+                         "SQ", "VQ", "TQ", "SS", "VS", "TS", "SH", "VH", "TH",
+                         "SI", "VI", "TI", "SY", "VY", "TY"};
+  for(int idxtype = 0; idxtype < 24; idxtype++){
+    if(type == types[idxtype]){
+      d->importList(idxtype, numEle, data, true);
+      return;
+    }
   }
-  return o;
+  Msg::Error("Unknown data type for list import");
+  throw 2;
+#else
+  Msg::Error("Views require the post-processing module");
+  throw -1;
+#endif
 }
+
+void gmsh::view::probe(const int tag, const double x, const double y,
+                       const double z, std::vector<double> &value,
+                       const int step, const int numComp,
+                       const bool gradient, const double tolerance,
+                       const std::vector<double> xElemCoord,
+                       const std::vector<double> yElemCoord,
+                       const std::vector<double> zElemCoord)
+{
+  if(!_isInitialized()){ throw -1; }
+#if defined(HAVE_POST)
+  PView *view = PView::getViewByTag(tag);
+  if(!view){
+    Msg::Error("Unknown view with tag %d", tag);
+    throw 2;
+  }
+  PViewData *data = view->getData();
+  if(!data){ throw 2; }
+  value.clear();
+  std::vector<double> val(9 * data->getNumTimeSteps());
+  bool found = false;
+  int qn = 0;
+  double *qx = 0, *qy = 0, *qz = 0;
+  if(xElemCoord.size() && yElemCoord.size() && zElemCoord.size() &&
+     xElemCoord.size() == yElemCoord.size() &&
+     xElemCoord.size() == zElemCoord.size()){
+    qn = xElemCoord.size();
+    qx = (double*)&xElemCoord[0];
+    qy = (double*)&yElemCoord[0];
+    qz = (double*)&zElemCoord[0];
+  }
+  switch(numComp){
+  case 1:
+    found = data->searchScalarWithTol
+      (x, y, z, &val[0], step, 0, tolerance, qn, qx, qy, qz, gradient);
+    break;
+  case 3:
+    found = data->searchVectorWithTol
+      (x, y, z, &val[0], step, 0, tolerance, qn, qx, qy, qz, gradient);
+    break;
+  case 9:
+    found = data->searchTensorWithTol
+      (x, y, z, &val[0], step, 0, tolerance, qn, qx, qy, qz, gradient);
+    break;
+  default:
+    found = data->searchScalarWithTol
+      (x, y, z, &val[0], step, 0, tolerance, qn, qx, qy, qz, gradient);
+    if(!found)
+      found = data->searchVectorWithTol
+        (x, y, z, &val[0], step, 0, tolerance, qn, qx, qy, qz, gradient);
+    if(!found)
+      found = data->searchTensorWithTol
+        (x, y, z, &val[0], step, 0, tolerance, qn, qx, qy, qz, gradient);
+    break;
+  }
+  if(found)
+    value.insert(value.end(), val.begin(), val.end());
+#else
+  Msg::Error("Views require the post-processing module");
+  throw -1;
 #endif
+}
 
-void gmshModelFieldSetNumber(const int tag, const std::string &option,
-                             const double value)
+void gmsh::view::write(const int tag, const std::string &fileName,
+                       const bool append)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
-#if defined(HAVE_MESH)
-  FieldOption *o = _getFieldOption(tag, option);
-  if(!o){ GMSH_ERROR(1); }
-  try { o->numericalValue(value); }
-  catch(...){
-    Msg::Error("Cannot set numerical value to option '%s' in field %i",
-               option.c_str(), tag);
-    GMSH_ERROR(1);
+  if(!_isInitialized()){ throw -1; }
+#if defined(HAVE_POST)
+  PView *view = PView::getViewByTag(tag);
+  if(!view){
+    Msg::Error("Unknown view with tag %d", tag);
+    throw 2;
   }
+  view->write(fileName, 10, append);
 #else
-  Msg::Error("Fields require the mesh module");
-  GMSH_ERROR(-1);
+  Msg::Error("Views require the post-processing module");
+  throw -1;
 #endif
 }
 
-void gmshModelFieldSetString(const int tag, const std::string &option,
-                             const std::string &value)
+// gmsh::plugin
+
+void gmsh::plugin::setNumber(const std::string &name, const std::string &option,
+                             const double value)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
-#if defined(HAVE_MESH)
-  FieldOption *o = _getFieldOption(tag, option);
-  if(!o){ GMSH_ERROR(1); }
-  try { o->string(value); }
-  catch(...){
-    Msg::Error("Cannot set string value to option '%s' in field %i",
-               option.c_str(), tag);
-    GMSH_ERROR(1);
+#if defined(HAVE_PLUGINS)
+  try {
+    PluginManager::instance()->setPluginOption(name, option, value);
+  }
+  catch(...) {
+    Msg::Error("Unknown plugin or plugin option");
+    throw 2;
   }
 #else
-  Msg::Error("Fields require the mesh module");
-  GMSH_ERROR(-1);
+  Msg::Error("Views require the post-processing and plugin modules");
+  throw -1;
 #endif
 }
 
-void gmshModelFieldSetNumbers(const int tag, const std::string &option,
-                              const std::vector<double> &value)
+void gmsh::plugin::setString(const std::string &name, const std::string &option,
+                             const std::string &value)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
-#if defined(HAVE_MESH)
-  FieldOption *o = _getFieldOption(tag, option);
-  if(!o){ GMSH_ERROR(1); }
+#if defined(HAVE_PLUGINS)
   try {
-    if(o->getType() == FIELD_OPTION_LIST) {
-      std::list<int> vl;
-      for(unsigned int i = 0; i < value.size(); i++)
-        vl.push_back((int)value[i]);
-      o->list(vl);
-    }
-    else{
-      std::list<double> vl;
-      for(unsigned int i = 0; i < value.size(); i++)
-        vl.push_back(value[i]);
-      o->listdouble(vl);
-    }
+    PluginManager::instance()->setPluginOption(name, option, value);
   }
-  catch(...){
-    Msg::Error("Cannot set numeric values to option '%s' in field %i",
-               option.c_str(), tag);
-    GMSH_ERROR(1);
+  catch(...) {
+    Msg::Error("Unknown plugin or plugin option");
+    throw 2;
   }
 #else
-  Msg::Error("Fields require the mesh module");
-  GMSH_ERROR(-1);
+  Msg::Error("Views require the post-processing and plugin modules");
+  throw -1;
 #endif
 }
 
-void gmshModelFieldSetAsBackground(const int tag)
+void gmsh::plugin::run(const std::string &name)
 {
-  if(!_isInitialized()){ GMSH_ERROR(-1); }
-#if defined(HAVE_MESH)
-  GModel::current()->getFields()->setBackgroundFieldId(tag);
+#if defined(HAVE_PLUGINS)
+  try {
+    PluginManager::instance()->action(name, "Run", 0);
+  }
+  catch(...) {
+    Msg::Error("Unknown plugin or plugin action");
+    throw 2;
+  }
 #else
-  Msg::Error("Fields require the mesh module");
-  GMSH_ERROR(-1);
+  Msg::Error("Views require the post-processing and plugin modules");
+  throw -1;
 #endif
 }
-
diff --git a/Common/gmsh.h b/Common/gmsh.h
index 30cd91821c1b5bec0d1ab9f49da46eb11af20eaf..594ecb6bd338e46d412ac0670c9ca615b3ee9638 100644
--- a/Common/gmsh.h
+++ b/Common/gmsh.h
@@ -32,540 +32,855 @@
 #define GMSH_API
 #endif
 
-// A geometrical entity in the Gmsh API is represented by two integers: its
-// dimension (dim = 0, 1, 2 or 3) and its tag (its unique identifier). When
-// dealing with multiple geometrical entities of possibly different dimensions,
-// the entities are packed as a vector of (dim, tag) integer pairs.
-typedef std::vector<std::pair<int, int> > vector_pair;
-
-// -----------------------------------------------------------------------------
-// Module "gmsh": top-level functions
-// -----------------------------------------------------------------------------
-
-// Initializes Gmsh. `gmshInitialize()' must be called before any call to the
-// other functions in the API. If argc and argv are are provided, they will be
-// handled in the same way as the command line arguments in the Gmsh app.
-GMSH_API void gmshInitialize(int argc = 0, char **argv = 0);
-
-// Finalizes Gmsh. This must be called when you are done using the Gmsh API.
-GMSH_API void gmshFinalize();
-
-// Opens a file and creates one (or more) new model(s). Equivalent to the
-// File->Open menu in the Gmsh app. Handling of the file depends on its
-// extension and/or its contents.
-GMSH_API void gmshOpen(const std::string &fileName);
-
-// Merges a file. Equivalent to the File->Merge menu in the Gmsh app. Handling
-// of the file depends on its extension and/or its contents.
-GMSH_API void gmshMerge(const std::string &fileName);
-
-// Exports a file. The export format is determined by the file extension.
-GMSH_API void gmshExport(const std::string &fileName);
-
-// Clears all loaded models and post-processing data, and creates a new empty
-// model.
-GMSH_API void gmshClear();
-
-// -----------------------------------------------------------------------------
-// Module "gmshOption": global option handling functions
-// -----------------------------------------------------------------------------
-
-// Sets a numerical option to `value'. `name' is of the form "category.option"
-// or "category[num].option". Available categories and options are listed in the
-// Gmsh reference manual.
-GMSH_API void gmshOptionSetNumber(const std::string &name, const double value);
-
-// Gets the `value' of a numerical option.
-GMSH_API void gmshOptionGetNumber(const std::string &name, double &value);
-
-// Sets a string option to `value'.
-GMSH_API void gmshOptionSetString(const std::string &name,
-                                  const std::string &value);
-
-// Gets the `value' of a string option.
-GMSH_API void gmshOptionGetString(const std::string &name, std::string &value);
-
-// -----------------------------------------------------------------------------
-// Module "gmshModel": per-model functions
-// -----------------------------------------------------------------------------
-
-// Creates a new model, with name `name', and sets it as the current model.
-GMSH_API void gmshModelCreate(const std::string &name);
-
-// Deletes the current model.
-GMSH_API void gmshModelDelete();
-
-// Lists the names of all models.
-GMSH_API void gmshModelList(std::vector<std::string> &names);
-
-// Sets the current model to the model with name `name'. If several models have
-// the same name, selects the one that was created first.
-GMSH_API void gmshModelSetCurrent(const std::string &name);
-
-// Gets all the (elementary) geometrical entities in the current model. If `dim'
-// is >= 0, returns only the entities of the specified dimension (e.g. points if
-// `dim' == 0). The entities are returned as a vector of (dim, tag) integer
-// pairs.
-GMSH_API void gmshModelGetEntities(vector_pair &dimTags, const int dim = -1);
-
-// Gets all the physical groups in the current model. If `dim' is >= 0, returns
-// only the entities of the specified dimension (e.g. physical points if `dim'
-// == 0). The entities are returned as a vector of (dim, tag) integer pairs.
-GMSH_API void gmshModelGetPhysicalGroups(vector_pair &dimTags,
-                                         const int dim = -1);
-
-// Gets the tags of all the (elementary) geometrical entities grouped in the
-// physical group of dimension `dim' and tag `tag'.
-GMSH_API void gmshModelGetEntitiesForPhysicalGroup(const int dim, const int tag,
-                                                   std::vector<int> &tags);
-
-// Adds a physical group of dimension `dim', grouping the elementary entities
-// with tags `tags'. The function returns the tag of the physical group, equal
-// to `tag' if `tag' > 0, or a new tag if not.
-GMSH_API int gmshModelAddPhysicalGroup(const int dim,
-                                       const std::vector<int> &tags,
-                                       int tag = -1);
-
-// Sets the name of the physical group of dimension `dim' and tag `tag'.
-GMSH_API void gmshModelSetPhysicalName(const int dim, const int tag,
-                                       const std::string &name);
-
-// Gets the name of the physical group of dimension `dim' and tag `tag'.
-GMSH_API void gmshModelGetPhysicalName(const int dim, const int tag,
-                                       std::string &name);
-
-// Gets the boundary of the geometrical entities `dimTags'. Returns in
-// `outDimTags' the boundary of the individual entities (if `combined' is false)
-// or the boundary of the combined geometrical shape formed by all input
-// entities (if `combined' is true). Returns tags multiplied by the sign of the
-// boundary entity if `oriented' is true. Applies the boundary operator
-// recursively down to dimension 0 (i.e. to points) if `recursive' is true.
-GMSH_API void gmshModelGetBoundary(const vector_pair &dimTags,
-                                   vector_pair &outDimTags,
-                                   const bool combined = true,
-                                   const bool oriented = true,
-                                   const bool recursive = false);
-
-// Gets the (elementary) geometrical entities in the bounding box defined by two
-// points (xmin, ymin, zmin) and (xmax, ymax, zmax).
-GMSH_API void gmshModelGetEntitiesInBoundingBox(const double xmin,
-                                                const double ymin,
-                                                const double zmin,
-                                                const double xmax,
-                                                const double ymax,
-                                                const double zmax,
-                                                vector_pair &tags,
-                                                const int dim=-1);
-
-// Gets the bounding box (xmin, ymin, zmin), (xmax, ymax, zmax) of the
-// geometrical entity of dimension `dim' and tag `tag'.
-GMSH_API void gmshModelGetBoundingBox(const int dim, const int tag, double &xmin,
-                                      double &ymin, double &zmin, double &xmax,
-                                      double &ymax, double &zmax);
-
-// Adds a discrete geometrical entity (defined by a mesh) of dimension `dim' in
-// the current model. The function returns the tag of the new discrete entity,
-// equal to `tag' if `tag' > 0, or a new tag if not. `boundary' specifies the
-// tags of the entities on the boundary of the entity, if any. Specyfing
-// `bounday' allows Gmsh to maintain the topology of the overall model.
-GMSH_API int gmshModelAddDiscreteEntity(const int dim,
-                                        const int tag = -1,
-                                        const std::vector<int> &boundary =
-                                        std::vector<int>());
-
-// Removes the entities `dimTags' of the current model. If `recursive' is true,
-// remove all the entities on their bundaries, down to dimension 0.
-GMSH_API void gmshModelRemove(const vector_pair &dimTags,
+namespace gmsh { // Top-level functions
+
+  // A geometrical entity in the Gmsh API is represented by two integers: its
+  // dimension (dim = 0, 1, 2 or 3) and its tag (its unique, strictly positive
+  // identifier). When dealing with multiple geometrical entities of possibly
+  // different dimensions, the entities are packed as a vector of (dim, tag)
+  // integer pairs.
+  typedef std::vector<std::pair<int, int> > vector_pair;
+
+  // Initializes Gmsh. This must be called before any call to the other
+  // functions in the API. If argc and argv are provided, they will be handled
+  // in the same way as the command line arguments in the Gmsh app.
+  GMSH_API void initialize(int argc = 0, char **argv = 0);
+
+  // Finalizes Gmsh. This must be called when you are done using the Gmsh API.
+  GMSH_API void finalize();
+
+  // Opens a file and adds one (or more) new model(s). Equivalent to the
+  // `File->Open' menu in the Gmsh app. Handling of the file depends on its
+  // extension and/or its contents.
+  GMSH_API void open(const std::string &fileName);
+
+  // Merges a file. Equivalent to the `File->Merge' menu in the Gmsh
+  // app. Handling of the file depends on its extension and/or its contents.
+  GMSH_API void merge(const std::string &fileName);
+
+  // Writes a file. The export format is determined by the file extension.
+  GMSH_API void write(const std::string &fileName);
+
+  // Clears all loaded models and post-processing data, and adds a new empty
+  // model.
+  GMSH_API void clear();
+
+  namespace option { // Global option handling functions
+
+    // Sets a numerical option to `value'. `name' is of the form
+    // "category.option" or "category[num].option". Available categories and
+    // options are listed in the Gmsh reference manual.
+    GMSH_API void setNumber(const std::string &name, const double value);
+
+    // Gets the `value' of a numerical option.
+    GMSH_API void getNumber(const std::string &name, double &value);
+
+    // Sets a string option to `value'.
+    GMSH_API void setString(const std::string &name,
+                            const std::string &value);
+
+    // Gets the `value' of a string option.
+    GMSH_API void getString(const std::string &name, std::string &value);
+
+  } // namespace option
+
+  namespace model { // Per-model functions
+
+    // Adds a new model, with name `name', and sets it as the current model.
+    GMSH_API void add(const std::string &name);
+
+    // Removes the current model.
+    GMSH_API void remove();
+
+    // Lists the names of all models.
+    GMSH_API void list(std::vector<std::string> &names);
+
+    // Sets the current model to the model with name `name'. If several models
+    // have the same name, selects the one that was added first.
+    GMSH_API void setCurrent(const std::string &name);
+
+    // Gets all the (elementary) geometrical entities in the current model. If
+    // `dim' is >= 0, returns only the entities of the specified dimension
+    // (e.g. points if `dim' == 0). The entities are returned as a vector of
+    // (dim, tag) integer pairs.
+    GMSH_API void getEntities(vector_pair &dimTags, const int dim = -1);
+
+    // Gets all the physical groups in the current model. If `dim' is >= 0,
+    // returns only the entities of the specified dimension (e.g. physical
+    // points if `dim' == 0). The entities are returned as a vector of (dim,
+    // tag) integer pairs.
+    GMSH_API void getPhysicalGroups(vector_pair &dimTags,
+                                    const int dim = -1);
+
+    // Gets the tags of all the (elementary) geometrical entities making up the
+    // physical group of dimension `dim' and tag `tag'.
+    GMSH_API void getEntitiesForPhysicalGroup(const int dim, const int tag,
+                                              std::vector<int> &tags);
+
+    // Adds a physical group of dimension `dim', grouping the elementary
+    // entities with tags `tags'. The function returns the tag of the physical
+    // group, equal to `tag' if `tag' is positive, or a new tag if `tag' < 0.
+    GMSH_API int addPhysicalGroup(const int dim,
+                                  const std::vector<int> &tags,
+                                  int tag = -1);
+
+    // Sets the name of the physical group of dimension `dim' and tag `tag'.
+    GMSH_API void setPhysicalName(const int dim, const int tag,
+                                  const std::string &name);
+
+    // Gets the name of the physical group of dimension `dim' and tag `tag'.
+    GMSH_API void getPhysicalName(const int dim, const int tag,
+                                  std::string &name);
+
+    // Gets the boundary of the geometrical entities `dimTags'. Returns in
+    // `outDimTags' the boundary of the individual entities (if `combined' is
+    // false) or the boundary of the combined geometrical shape formed by all
+    // input entities (if `combined' is true). Returns tags multiplied by the
+    // sign of the boundary entity if `oriented' is true. Applies the boundary
+    // operator recursively down to dimension 0 (i.e. to points) if `recursive'
+    // is true.
+    GMSH_API void getBoundary(const vector_pair &dimTags,
+                              vector_pair &outDimTags,
+                              const bool combined = true,
+                              const bool oriented = true,
                               const bool recursive = false);
 
-// Generates a mesh of the current model, up to dimension `dim' (0, 1, 2 or 3).
-GMSH_API void gmshModelMesh(const int dim);
-
-// Gets the mesh vertices of the entity of dimension `dim' and `tag'
-// tag. `vertextags' contains the vertex tags (unique identification
-// numbers). `coord` is a vector of length `3 * vertexTags.size()' that contains
-// the (x, y, z) coordinates of the vertices. `parametricCoord` contains the
-// parametric coordinates of the vertices, if available. The length of
-// `parametricCoord` can be 0, `vertexTags.size()' or `2 * vertexTags.size()'.
-GMSH_API void gmshModelGetMeshVertices(const int dim, const int tag,
-                                       std::vector<int> &vertexTags,
-                                       std::vector<double> &coord,
-                                       std::vector<double> &parametricCoord);
-
-// Gets the mesh elements of the entity of dimension `dim' and `tag'
-// tag. `types' contains the MSH types (e.g. 2 for 3-node triangles -- see the
-// Gmsh reference manual). `elementTags' is a vector of length `types.size()';
-// each entry is a vector containing the tags (unique identifiers) of the
-// elements of the corresponding type. `vertexTags' is a vector of length
-// `types.size()'; each entry is a vector of length equal to the number of
-// elements of the give type, times the number of vertices per element, that
-// contains the vertex tags of all the elements of the given type.
-GMSH_API void gmshModelGetMeshElements(const int dim, const int tag,
-                                       std::vector<int> &types,
-                                       std::vector<std::vector<int> > &elementTags,
-                                       std::vector<std::vector<int> > &vertexTags);
-
-// Sets the mesh vertices in the geometrical entity of dimension `dim' and tag
-// `tag'. `vertextags' contains the vertex tags (unique identification
-// numbers). `coord` is a vector of length `3 * vertexTags.size()' that contains
-// the (x, y, z) coordinates of the vertices. The optional `parametricCoord`
-// vector contains the parametric coordinates of the vertices, if any. The
-// length of `parametricCoord` can be 0 or `dim * vertexTags.size()'.
-GMSH_API void gmshModelSetMeshVertices(const int dim, const int tag,
-                                       const std::vector<int> &vertexTags,
-                                       const std::vector<double> &coord,
-                                       const std::vector<double> &parametricCoord =
-                                       std::vector<double>());
-
-// Sets the mesh elements of the entity of dimension `dim' and `tag'
-// tag. `types' contains the MSH types (e.g. 2 for 3-node triangles -- see the
-// Gmsh reference manual). `elementTags' is a vector of length `types.size()';
-// each entry is a vector containing the tags (unique identifiers) of the
-// elements of the corresponding type. `vertexTags' is a vector of length
-// `types.size()'; each entry is a vector of length equal to the number of
-// elements of the give type, times the number of vertices per element, that
-// contains the vertex tags of all the elements of the given type.
-GMSH_API void gmshModelSetMeshElements(const int dim, const int tag,
-                                       const std::vector<int> &types,
-                                       const std::vector<std::vector<int> > &elementTags,
-                                       const std::vector<std::vector<int> > &vertexTags);
-
-// Gets the coordinates and the parametric coordinates (if any) of the mesh
-// vertex with tag `tag'. This is an inefficient way of accessing mesh vertex
-// data, as it relies on a dynamic cache stored in the model. For large meshes
-// all the vertices in the model should be numbered in a continuous sequence of
-// tags from 1 to N to maintain reasonnable performance (in this case the
-// internal cache is based on a vector; otherwise it uses a map).
-GMSH_API void gmshModelGetMeshVertex(const int vertexTag,
-                                     std::vector<double> &coord,
-                                     std::vector<double> &parametricCoord);
-
-// Gets the type and vertex tags of the mesh element with tag `tag'. This is an
-// inefficient way of accessing mesh element data, as it relies on a dynamic
-// cache stored in the model. For large meshes all the elements in the model
-// should be numbered in a continuous sequence of tags from 1 to N to maintain
-// reasonnable performance (in this case the internal cache is based on a
-// vector; otherwise it uses a map).
-GMSH_API void gmshModelGetMeshElement(const int elementTag, int &type,
-                                      std::vector<int> &vertexTags);
-
-// Sets a mesh size constraint on the geometrical entities `dimTags'. Currently
-// only entities of dimension 0 (points) are handled.
-GMSH_API void gmshModelSetMeshSize(const vector_pair &dimTags, const double size);
-
-// Sets a transfinite meshing constraint on the line `tag', with `numVertices'
-// mesh vertices distributed according to `type' and `coef'. Currently supported
-// types are "Progression" (geometrical progression with power `coef') and
-// "Bump" (refinement toward both extreminties of the line0.
-GMSH_API void gmshModelSetTransfiniteLine(const int tag, const int numVertices,
-                                          const std::string &type = "Progression",
-                                          const double coef = 1.);
-
-// Sets a transfinite meshing constraint on the surface `tag'. `arrangement'
-// describes the arrangement of the triangles when the surface is not flagged as
-// recombined: currently supported values are "Left", "Right", "AlternateLeft"
-// and "AlternateRight". `cornerTags' can be used to specify the (3 or 4)
-// corners of the transfinite interpolation explicitly; specifying the corners
-// explicitly is mandatory if the surface has more that 3 or 4 points on its
-// boundary.
-GMSH_API void gmshModelSetTransfiniteSurface(const int tag,
-                                             const std::string &arrangement = "Left",
-                                             const std::vector<int> &cornerTags =
-                                             std::vector<int>());
-
-// Sets a transfinite meshing constraint on the surface `tag'. `cornerTags' can
-// be used to specify the (6 or 8) corners of the transfinite interpolation
-// explicitly.
-GMSH_API void gmshModelSetTransfiniteVolume(const int tag,
-                                            const std::vector<int> &cornerTags =
-                                            std::vector<int>());
+    // Gets the (elementary) geometrical entities in the bounding box defined by the
+    // two points (xmin, ymin, zmin) and (xmax, ymax, zmax). If `dim' is >= 0,
+    // returns only the entities of the specified dimension (e.g. points if `dim' ==
+    // 0).
+    GMSH_API void getEntitiesInBoundingBox(const double xmin,
+                                           const double ymin,
+                                           const double zmin,
+                                           const double xmax,
+                                           const double ymax,
+                                           const double zmax,
+                                           vector_pair &tags,
+                                           const int dim = -1);
+
+    // Gets the bounding box (xmin, ymin, zmin), (xmax, ymax, zmax) of the
+    // geometrical entity of dimension `dim' and tag `tag'.
+    GMSH_API void getBoundingBox(const int dim, const int tag, double &xmin,
+                                 double &ymin, double &zmin, double &xmax,
+                                 double &ymax, double &zmax);
+
+    // Adds a discrete geometrical entity (defined by a mesh) of dimension `dim'
+    // in the current model. The function returns the tag of the new discrete
+    // entity, equal to `tag' if `tag' is positive, or a new tag if `tag' <
+    // 0. `boundary' specifies the tags of the entities on the boundary of the
+    // discrete entity, if any. Specyfing `boundary' allows Gmsh to construct
+    // the topology of the overall model.
+    GMSH_API int addDiscreteEntity(const int dim,
+                                   const int tag = -1,
+                                   const std::vector<int> &boundary =
+                                   std::vector<int>());
 
-// Sets a recombination meshing constraint on the geometrical entity of
-// dimension `dim' and tag `tag'. Currently only entities of dimension 2 (to
-// recombine triangles into quadrangles) are supported.
-GMSH_API void gmshModelSetRecombine(const int dim, const int tag);
-
-// Sets a smoothing meshing constraint on the geometrical entity of dimension
-// `dim' and tag `tag'. `val' iterations of a Laplace smoother will be applied.
-GMSH_API void gmshModelSetSmoothing(const int dim, const int tag, const int val);
-
-// Sets a reverse meshing constraint on the geometrical entity of dimension
-// `dim' and tag `tag'. If `val' is true, the mesh orientation will be reverse
-// with respect to the natural mesh orientation (i.e. the orientation consistent
-// with the orientation of the geometrical entity). If `val' is false, the mesh
-// is left as-is.
-GMSH_API void gmshModelSetReverseMesh(const int dim, const int tag,
-                                      const bool val = true);
-
-// Emebds the geometrical entities of dimension `dim' and tags `tags' in the
-// (inDim, inTag) geometrical entity. `inDim' must be strictly greater than
-// `dim'.
-GMSH_API void gmshModelEmbed(const int dim, const std::vector<int> &tags,
-                             const int inDim, const int inTag);
-
-// -----------------------------------------------------------------------------
-// Section "gmshModelGeo": built-in CAD kernel functions for current model
-// -----------------------------------------------------------------------------
-
-GMSH_API int gmshModelGeoAddPoint(const double x, const double y, const double z,
-                                  const double meshSize = 0., const int tag = -1);
-GMSH_API int gmshModelGeoAddLine(const int startTag, const int endTag,
-                                 const int tag = -1);
-GMSH_API int gmshModelGeoAddCircleArc(const int startTag, const int centerTag,
-                                      const int endTag, const int tag = -1,
-                                      const double nx = 0., const double ny = 0.,
-                                      const double nz = 0.);
-GMSH_API int gmshModelGeoAddEllipseArc(const int startTag, const int centerTag,
-                                       const int majorTag, const int endTag,
-                                       const int tag = -1, const double nx = 0.,
-                                       const double ny = 0., const double nz = 0.);
-GMSH_API int gmshModelGeoAddSpline(const std::vector<int> &vertexTags,
-                                   const int tag = -1);
-GMSH_API int gmshModelGeoAddBSpline(const std::vector<int> &vertexTags,
-                                    const int tag = -1);
-GMSH_API int gmshModelGeoAddBezier(const std::vector<int> &vertexTags,
-                                   const int tag = -1);
-GMSH_API int gmshModelGeoAddLineLoop(const std::vector<int> &edgeTags,
-                                     const int tag = -1);
-GMSH_API int gmshModelGeoAddPlaneSurface(const std::vector<int> &wireTags,
-                                         const int tag = -1);
-GMSH_API int gmshModelGeoAddSurfaceFilling(const std::vector<int> &wireTags,
-                                           const int tag = -1,
-                                           const int sphereCenterTag = -1);
-GMSH_API int gmshModelGeoAddSurfaceLoop(const std::vector<int> &faceTags,
-                                        const int tag = -1);
-GMSH_API int gmshModelGeoAddVolume(const std::vector<int> &shellTags,
-                                   const int tag = -1);
-GMSH_API void gmshModelGeoExtrude(const vector_pair &dimTags,
-                                  const double dx, const double dy, const double dz,
-                                  vector_pair &outDimTags,
-                                  const std::vector<int> &numElements =
-                                  std::vector<int>(),
-                                  const std::vector<double> &heights =
-                                  std::vector<double>(),
-                                  const bool recombine = false);
-GMSH_API void gmshModelGeoRevolve(const vector_pair &dimTags,
-                                  const double x, const double y, const double z,
-                                  const double ax, const double ay,
-                                  const double az, const double angle,
-                                  vector_pair &outDimTags,
-                                  const std::vector<int> &numElements =
-                                  std::vector<int>(),
-                                  const std::vector<double> &heights =
-                                  std::vector<double>(),
-                                  const bool recombine = false);
-GMSH_API void gmshModelGeoTwist(const vector_pair &dimTags,
-                                const double x, const double y, const double z,
-                                const double dx, const double dy, const double dz,
-                                const double ax, const double ay, const double az,
-                                const double angle,
-                                vector_pair &outDimTags,
-                                const std::vector<int> &numElements =
-                                std::vector<int>(),
-                                const std::vector<double> &heights =
-                                std::vector<double>(),
-                                const bool recombine = false);
-GMSH_API void gmshModelGeoTranslate(const vector_pair &dimTags, const double dx,
-                                    const double dy, const double dz);
-GMSH_API void gmshModelGeoRotate(const vector_pair &dimTags, const double x,
-                                 const double y, const double z, const double ax,
-                                 const double ay, const double az,
-                                 const double angle);
-GMSH_API void gmshModelGeoDilate(const vector_pair &dimTags, const double x,
-                                 const double y, const double z, const double a,
-                                 const double b, const double c);
-GMSH_API void gmshModelGeoSymmetry(const vector_pair &dimTags, const double a,
-                                   const double b, const double c, const double d);
-GMSH_API void gmshModelGeoCopy(const vector_pair &dimTags, vector_pair &outDimTags);
-GMSH_API void gmshModelGeoRemove(const vector_pair &dimTags,
+    // Removes the entities `dimTags' of the current model. If `recursive' is true,
+    // remove all the entities on their boundaries, down to dimension 0.
+    GMSH_API void removeEntities(const vector_pair &dimTags,
                                  const bool recursive = false);
-GMSH_API void gmshModelGeoRemoveAllDuplicates();
-GMSH_API void gmshModelGeoSetMeshSize(const vector_pair &dimTags, const double size);
-GMSH_API void gmshModelGeoSetTransfiniteLine(const int tag, const int nPoints,
-                                             const std::string &type = "Progression",
-                                             const double coef = 1.);
-GMSH_API void gmshModelGeoSetTransfiniteSurface(const int tag,
-                                                const std::string &arrangement = "Left",
-                                                const std::vector<int> &cornerTags =
-                                                std::vector<int>());
-GMSH_API void gmshModelGeoSetTransfiniteVolume(const int tag,
-                                               const std::vector<int> &cornerTags =
-                                               std::vector<int>());
-GMSH_API void gmshModelGeoSetRecombine(const int dim, const int tag,
-                                       const double angle = 45.);
-GMSH_API void gmshModelGeoSetSmoothing(const int dim, const int tag,
-                                       const int val);
-GMSH_API void gmshModelGeoSetReverseMesh(const int dim, const int tag,
-                                         const bool val = true);
-GMSH_API void gmshModelGeoSynchronize();
-
-// -----------------------------------------------------------------------------
-// Section "gmshModelOcc": OpenCASCADE CAD kernel functions for current model
-// -----------------------------------------------------------------------------
-
-GMSH_API int gmshModelOccAddPoint(const double x, const double y, const double z,
-                                  const double meshSize = 0., const int tag = -1);
-GMSH_API int gmshModelOccAddLine(const int startTag, const int endTag,
-                                 const int tag = -1);
-GMSH_API int gmshModelOccAddCircleArc(const int startTag, const int centerTag,
-                                      const int endTag, const int tag = -1);
-GMSH_API int gmshModelOccAddCircle(const double x, const double y, const double z,
-                                   const double r, const int tag = -1,
-                                   const double angle1 = 0.,
-                                   const double angle2 = 2*M_PI);
-GMSH_API int gmshModelOccAddEllipseArc(const int startTag, const int centerTag,
-                                       const int endTag, const int tag = -1);
-GMSH_API int gmshModelOccAddEllipse(const double x, const double y, const double z,
-                                    const double r1, const double r2,
-                                    const int tag = -1,
-                                    const double angle1 = 0.,
-                                    const double angle2 = 2*M_PI);
-GMSH_API int gmshModelOccAddSpline(const std::vector<int> &vertexTags,
-                                   const int tag = -1);
-GMSH_API int gmshModelOccAddBezier(const std::vector<int> &vertexTags,
+
+    namespace mesh { // Per-model meshing functions
+
+      // Generates a mesh of the current model, up to dimension `dim' (0, 1, 2
+      // or 3).
+      GMSH_API void generate(const int dim);
+
+      // Gets the last entities (if any) where a meshing error
+      // occurred. Currently only populated by the new 3D meshing algorithms.
+      GMSH_API void getLastEntityError(vector_pair &dimTags);
+
+      // Gets the last mesh vertices (if any) where a meshing error
+      // occurred. Currently only populated by the new 3D meshing algorithms.
+      GMSH_API void getLastVertexError(std::vector<int> &vertexTags);
+
+      // Gets the mesh vertices of the entity of dimension `dim' and `tag'
+      // tag. `vertextags' contains the vertex tags (their unique, strictly
+      // positive identification numbers). `coord` is a vector of length `3 *
+      // vertexTags.size()' that contains the (x, y, z) coordinates of the
+      // vertices, concatenated. `parametricCoord` contains the parametric
+      // coordinates of the vertices, if available. The length of
+      // `parametricCoord` can be 0 or `dim * vertexTags.size()'.
+      GMSH_API void getVertices(const int dim, const int tag,
+                                std::vector<int> &vertexTags,
+                                std::vector<double> &coord,
+                                std::vector<double> &parametricCoord);
+
+      // Gets the mesh elements of the entity of dimension `dim' and `tag'
+      // tag. `types' contains the MSH types of the elements (e.g. `2' for
+      // 3-node triangles: see the Gmsh reference manual). `elementTags' is a
+      // vector of length `types.size()'; each entry is a vector containing the
+      // tags (unique, strictly positive identifiers) of the elements of the
+      // corresponding type. `vertexTags' is also a vector of length
+      // `types.size()'; each entry is a vector of length equal to the number of
+      // elements of the given type times the number of vertices for this type
+      // of element, that contains the vertex tags of all the elements of the
+      // given type, concatenated.
+      GMSH_API void getElements(const int dim, const int tag,
+                                std::vector<int> &types,
+                                std::vector<std::vector<int> > &elementTags,
+                                std::vector<std::vector<int> > &vertexTags);
+
+      // Sets the mesh vertices in the geometrical entity of dimension `dim' and
+      // tag `tag'. `vertextags' contains the vertex tags (their unique,
+      // strictly positive identification numbers). `coord` is a vector of
+      // length `3 * vertexTags.size()' that contains the (x, y, z) coordinates
+      // of the vertices, concatenated. The optional `parametricCoord` vector
+      // contains the parametric coordinates of the vertices, if any. The length
+      // of `parametricCoord` can be 0 or `dim * vertexTags.size()'.
+      GMSH_API void setVertices(const int dim, const int tag,
+                                const std::vector<int> &vertexTags,
+                                const std::vector<double> &coord,
+                                const std::vector<double> &parametricCoord =
+                                std::vector<double>());
+
+      // Sets the mesh elements of the entity of dimension `dim' and `tag'
+      // tag. `types' contains the MSH types of the elements (e.g. `2' for
+      // 3-node triangles: see the Gmsh reference manual). `elementTags' is a
+      // vector of length `types.size()'; each entry is a vector containing the
+      // tags (unique, strictly positive identifiers) of the elements of the
+      // corresponding type. `vertexTags' is also a vector of length
+      // `types.size()'; each entry is a vector of length equal to the number of
+      // elements of the give type times the number of vertices per element,
+      // that contains the vertex tags of all the elements of the given type,
+      // concatenated.
+      GMSH_API void setElements(const int dim, const int tag,
+                                const std::vector<int> &types,
+                                const std::vector<std::vector<int> > &elementTags,
+                                const std::vector<std::vector<int> > &vertexTags);
+
+      // Gets the coordinates and the parametric coordinates (if any) of the
+      // mesh vertex with tag `tag'. This is a useful by inefficient way of
+      // accessing mesh vertex data, as it relies on a cache stored in the
+      // model. For large meshes all the vertices in the model should be
+      // numbered in a continuous sequence of tags from 1 to N to maintain
+      // reasonnable performance (in this case the internal cache is based on a
+      // vector; otherwise it uses a map).
+      GMSH_API void getVertex(const int vertexTag,
+                              std::vector<double> &coord,
+                              std::vector<double> &parametricCoord);
+
+      // Gets the type and vertex tags of the mesh element with tag `tag'. This
+      // is a useful but inefficient way of accessing mesh element data, as it
+      // relies on a cache stored in the model. For large meshes all the
+      // elements in the model should be numbered in a continuous sequence of
+      // tags from 1 to N to maintain reasonnable performance (in this case the
+      // internal cache is based on a vector; otherwise it uses a map).
+      GMSH_API void getElement(const int elementTag, int &type,
+                               std::vector<int> &vertexTags);
+
+      // Sets a mesh size constraint on the geometrical entities
+      // `dimTags'. Currently only entities of dimension 0 (points) are handled.
+      GMSH_API void setSize(const vector_pair &dimTags, const double size);
+
+      // Sets a transfinite meshing constraint on the line `tag', with
+      // `numVertices' mesh vertices distributed according to `type' and
+      // `coef'. Currently supported types are "Progression" (geometrical
+      // progression with power `coef') and "Bump" (refinement toward both
+      // extreminties of the line).
+      GMSH_API void setTransfiniteLine(const int tag, const int numVertices,
+                                       const std::string &type = "Progression",
+                                       const double coef = 1.);
+
+      // Sets a transfinite meshing constraint on the surface
+      // `tag'. `arrangement' describes the arrangement of the triangles when
+      // the surface is not flagged as recombined: currently supported values
+      // are "Left", "Right", "AlternateLeft" and "AlternateRight". `cornerTags'
+      // can be used to specify the (3 or 4) corners of the transfinite
+      // interpolation explicitly; specifying the corners explicitly is
+      // mandatory if the surface has more that 3 or 4 points on its boundary.
+      GMSH_API void setTransfiniteSurface(const int tag,
+                                          const std::string &arrangement = "Left",
+                                          const std::vector<int> &cornerTags =
+                                          std::vector<int>());
+
+      // Sets a transfinite meshing constraint on the surface
+      // `tag'. `cornerTags' can be used to specify the (6 or 8) corners of the
+      // transfinite interpolation explicitly.
+      GMSH_API void setTransfiniteVolume(const int tag,
+                                         const std::vector<int> &cornerTags =
+                                         std::vector<int>());
+
+      // Sets a recombination meshing constraint on the geometrical entity of
+      // dimension `dim' and tag `tag'. Currently only entities of dimension 2
+      // (to recombine triangles into quadrangles) are supported.
+      GMSH_API void setRecombine(const int dim, const int tag);
+
+      // Sets a smoothing meshing constraint on the geometrical entity of
+      // dimension `dim' and tag `tag'. `val' iterations of a Laplace smoother
+      // are applied.
+      GMSH_API void setSmoothing(const int dim, const int tag, const int val);
+
+      // Sets a reverse meshing constraint on the geometrical entity of
+      // dimension `dim' and tag `tag'. If `val' is true, the mesh orientation
+      // will be reversed with respect to the natural mesh orientation (i.e. the
+      // orientation consistent with the orientation of the geometrical
+      // entity). If `val' is false, the mesh is left as-is.
+      GMSH_API void setReverse(const int dim, const int tag,
+                               const bool val = true);
+
+      // Emebds the geometrical entities of dimension `dim' and tags `tags' in
+      // the (inDim, inTag) geometrical entity. `inDim' must be strictly greater
+      // than `dim'.
+      GMSH_API void embed(const int dim, const std::vector<int> &tags,
+                          const int inDim, const int inTag);
+
+      namespace field { // Per-model mesh size field functions
+
+        // Adds a new mesh size field of type `type'. If `tag' is positive,
+        // assign the tag explcitly; otherwise a new tag is assigned
+        // automatically. Returns the field tag.
+        GMSH_API int add(const std::string &type, const int tag = -1);
+
+        // Removes the field with tag `tag'.
+        GMSH_API void remove(const int tag);
+
+        // Sets the numerical option `option' to value `value' for field `tag'.
+        GMSH_API void setNumber(const int tag, const std::string &option,
+                                const double value);
+
+        // Sets the string option `option' to value `value' for field `tag'.
+        GMSH_API void setString(const int tag, const std::string &option,
+                                const std::string &value);
+
+        // Sets the numerical list option `option' to value `value' for field
+        // `tag'.
+        GMSH_API void setNumbers(const int tag, const std::string &option,
+                                 const std::vector<double> &value);
+
+        // Sets the field `tag' as background mesh size field.
+        GMSH_API void setAsBackground(const int tag);
+
+      } // namespace field
+
+    } // namespace mesh
+
+    namespace geo { // Internal per-model GEO CAD kernel functions
+
+      // Adds a geometrical point in the internal GEO CAD representation, at
+      // coordinates (x, y, z). If `meshSize' is > 0, adds a meshing constraint
+      // at that point. If `tag' is positive, sets the tag explicitly; otherwise
+      // a new tag is selected automatically. Returns the tag of the
+      // point. (Note that the point will be added in the current model only
+      // after gmshModelGeoSynchronize() is called. This behavior holds for all
+      // the entities added in the gmshModelGeo module.)
+      GMSH_API int addPoint(const double x, const double y, const double z,
+                            const double meshSize = 0., const int tag = -1);
+
+      // Adds a straight line segment between the two points with tags
+      // `startTag' and `endTag'. If `tag' is positive, sets the tag explicitly;
+      // otherwise a new tag is selected automatically. Returns the tag of the
+      // line.
+      GMSH_API int addLine(const int startTag, const int endTag,
+                           const int tag = -1);
+
+      // Adds a circle arc (stricly smaller than Pi) between the two points with
+      // tags `startTag' and `endTag', with center `centertag'. If `tag' is
+      // positive, sets the tag explicitly; otherwise a new tag is selected
+      // automatically. If (`nx', `ny', `nz') != (0,0,0), explicitely sets the
+      // plane of the circle arc. Returns the tag of the circle arc.
+      GMSH_API int addCircleArc(const int startTag, const int centerTag,
+                                const int endTag, const int tag = -1,
+                                const double nx = 0., const double ny = 0.,
+                                const double nz = 0.);
+
+      // Adds an ellipse arc (stricly smaller than Pi) between the two points
+      // `startTag' and `endTag', with center `centertag' and major axis point
+      // `majorTag'. If `tag' is positive, sets the tag explicitly; otherwise a
+      // new tag is selected automatically. If (`nx', `ny', `nz') != (0,0,0),
+      // explicitely sets the plane of the circle arc. Returns the tag of the
+      // ellipse arc.
+      GMSH_API int addEllipseArc(const int startTag, const int centerTag,
+                                 const int majorTag, const int endTag,
+                                 const int tag = -1, const double nx = 0.,
+                                 const double ny = 0., const double nz = 0.);
+
+      // Adds a spline curve going through `vertexTags' points. If `tag' is
+      // positive, sets the tag explicitly; otherwise a new tag is selected
+      // automatically.  Returns the tag of the spline curve.
+      GMSH_API int addSpline(const std::vector<int> &vertexTags,
+                             const int tag = -1);
+
+      // Adds a b-spline curve with `vertexTags' control points. If `tag' is
+      // positive, sets the tag explicitly; otherwise a new tag is selected
+      // automatically.  Returns the tag of the b-spline curve.
+      GMSH_API int addBSpline(const std::vector<int> &vertexTags,
+                              const int tag = -1);
+
+      // Adds a Bezier curve with `vertexTags' control points. If `tag' is
+      // positive, sets the tag explicitly; otherwise a new tag is selected
+      // automatically.  Returns the tag of the Bezier curve.
+      GMSH_API int addBezier(const std::vector<int> &vertexTags,
+                             const int tag = -1);
+
+      // Adds a line loop (a closed wire) formed by `edgeTags'. `edgeTags'
+      // should contain (signed) tags of geometrical enties of dimension 1
+      // forming a closed loop: a negative tag signifies that the underlying
+      // edge is considered with reversed orientation. If `tag' is positive,
+      // sets the tag explicitly; otherwise a new tag is selected
+      // automatically. Returns the tag of the line loop.
+      GMSH_API int addLineLoop(const std::vector<int> &edgeTags,
+                               const int tag = -1);
+
+      // Adds a plane surface defined by one or more line loops `wireTags'. The
+      // first line loop defines the exterior contour; additional line loop
+      // define holes. If `tag' is positive, sets the tag explicitly; otherwise
+      // a new tag is selected automatically. Returns the tag of the surface.
+      GMSH_API int addPlaneSurface(const std::vector<int> &wireTags,
                                    const int tag = -1);
-GMSH_API int gmshModelOccAddBSpline(const std::vector<int> &vertexTags,
-                                    const int tag = -1);
-GMSH_API int gmshModelOccAddWire(const std::vector<int> &edgeTags,
-                                 const int tag = -1,
-                                 const bool checkClosed = false);
-GMSH_API int gmshModelOccAddLineLoop(const std::vector<int> &edgeTags,
-                                     const int tag = -1);
-GMSH_API int gmshModelOccAddRectangle(const double x, const double y,
-                                      const double z, const double dx,
-                                      const double dy,
-                                      const int tag = -1,
-                                      const double roundedRadius = 0.);
-GMSH_API int gmshModelOccAddDisk(const double xc, const double yc,
-                                 const double zc, const double rx,
-                                 const double ry, const int tag = -1);
-GMSH_API int gmshModelOccAddPlaneSurface(const std::vector<int> &wireTags,
-                                         const int tag = -1);
-GMSH_API int gmshModelOccAddSurfaceFilling(int wireTag, const int tag = -1);
-GMSH_API int gmshModelOccAddSurfaceLoop(const std::vector<int> &faceTags,
-                                        const int tag = -1);
-GMSH_API int gmshModelOccAddVolume(const std::vector<int> &shellTags,
+
+      // Adds a surface filling the line loops in `wireTags'. Currently only a
+      // single line loop is supported; this line loop should be composed by 3
+      // or 4 edges only. If `tag' is positive, sets the tag explicitly;
+      // otherwise a new tag is selected automatically. Returns the tag of the
+      // surface.
+      GMSH_API int addSurfaceFilling(const std::vector<int> &wireTags,
+                                     const int tag = -1,
+                                     const int sphereCenterTag = -1);
+
+      // Adds a surface loop (a closed shell) formed by `faceTags'.  If `tag' is
+      // positive, sets the tag explicitly; otherwise a new tag is selected
+      // automatically. Returns the tag of the surface loop.
+      GMSH_API int addSurfaceLoop(const std::vector<int> &faceTags,
+                                  const int tag = -1);
+
+      // Adds a volume defined by one or more surface loops `shellTags'. The
+      // first surface loop defines the exterior boundary; additional surface
+      // loop define holes. If `tag' is positive, sets the tag explicitly;
+      // otherwise a new tag is selected automatically. Returns the tag of the
+      // volume.
+      GMSH_API int addVolume(const std::vector<int> &shellTags,
+                             const int tag = -1);
+
+      // Extrudes the geometrical entities in `dimTags' by translation along
+      // (`dx', `dy', `dz'). Returns extruded entities in `outDimTags'. If
+      // `numElements' is not empty, also extrude the mesh: the entries in
+      // `numElements' give the number of elements in each layer. If `height' is
+      // not empty, it provides the (cummulative) height of the different
+      // layers, normalized to 1.
+      GMSH_API void extrude(const vector_pair &dimTags,
+                            const double dx, const double dy, const double dz,
+                            vector_pair &outDimTags,
+                            const std::vector<int> &numElements =
+                            std::vector<int>(),
+                            const std::vector<double> &heights =
+                            std::vector<double>(),
+                            const bool recombine = false);
+
+      // Extrudes the geometrical entities in `dimTags' by rotation of `angle'
+      // radians around the axis of revolution defined by the point (`x', `y',
+      // `z') and the direction (`ax', `ay', `az'). Returns extruded entities in
+      // `outDimTags'. If `numElements' is not empty, also extrude the mesh: the
+      // entries in `numElements' give the number of elements in each layer. If
+      // `height' is not empty, it provides the (cummulative) height of the
+      // different layers, normalized to 1.
+      GMSH_API void revolve(const vector_pair &dimTags,
+                            const double x, const double y, const double z,
+                            const double ax, const double ay,
+                            const double az, const double angle,
+                            vector_pair &outDimTags,
+                            const std::vector<int> &numElements =
+                            std::vector<int>(),
+                            const std::vector<double> &heights =
+                            std::vector<double>(),
+                            const bool recombine = false);
+
+      // Extrudes the geometrical entities in `dimTags' by a combined
+      // translation and rotation of `angle' radians, along (`dx', `dy', `dz')
+      // and around the axis of revolution defined by the point (`x', `y', `z')
+      // and the direction (`ax', `ay', `az'). Returns extruded entities in
+      // `outDimTags'. If `numElements' is not empty, also extrude the mesh: the
+      // entries in `numElements' give the number of elements in each layer. If
+      // `height' is not empty, it provides the (cummulative) height of the
+      // different layers, normalized to 1.
+      GMSH_API void twist(const vector_pair &dimTags,
+                          const double x, const double y, const double z,
+                          const double dx, const double dy, const double dz,
+                          const double ax, const double ay, const double az,
+                          const double angle,
+                          vector_pair &outDimTags,
+                          const std::vector<int> &numElements =
+                          std::vector<int>(),
+                          const std::vector<double> &heights =
+                          std::vector<double>(),
+                          const bool recombine = false);
+
+      // Translates the geometrical entities in `dimTags' along (`dx', `dy',
+      // `dz').
+      GMSH_API void translate(const vector_pair &dimTags, const double dx,
+                              const double dy, const double dz);
+
+      // Rotates the geometrical entities in `dimTags' of `angle' radians around
+      // the axis of revolution defined by the point (`x', `y', `z') and the
+      // direction (`ax', `ay', `az').
+      GMSH_API void rotate(const vector_pair &dimTags, const double x,
+                           const double y, const double z, const double ax,
+                           const double ay, const double az,
+                           const double angle);
+
+
+      // Scales the geometrical entities in `dimTag' by factors `a', `b' and `c'
+      // along the three coordinate axes; use (`x', `y', `z') as the center of
+      // the homothetic transformation.
+      GMSH_API void dilate(const vector_pair &dimTags, const double x,
+                           const double y, const double z, const double a,
+                           const double b, const double c);
+
+      // Applies a symmetry transformation to the geometrical entities in
+      // `dimTag', with respect to the plane of equation `a' * x + `b' * y + `c'
+      // * z + `d' = 0.
+      GMSH_API void symmetry(const vector_pair &dimTags, const double a,
+                             const double b, const double c, const double d);
+
+      // Copies the entities in `dimTags'; the new entities are returned in
+      // `outDimTags'.
+      GMSH_API void copy(const vector_pair &dimTags, vector_pair &outDimTags);
+
+      // Removes the entities `dimTags'. If `recursive' is true, remove all the
+      // entities on their boundaries, down to dimension 0.
+      GMSH_API void remove(const vector_pair &dimTags,
+                           const bool recursive = false);
+
+      // Remove all duplicate entities (different entities at the same
+      // geometrical location).
+      GMSH_API void removeAllDuplicates();
+
+      // Synchronize the internal GEO CAD representation with the current Gmsh
+      // model. This can be called at any time, but since it involves a non
+      // trivial amount of processing, the number of synchronization points
+      // should normally be minimized.
+      GMSH_API void synchronize();
+
+      namespace mesh { // geo-specific meshing constraints
+
+        // Sets a mesh size constraint on the geometrical entities
+        // `dimTags'. Currently only entities of dimension 0 (points) are
+        // handled.
+        GMSH_API void setSize(const vector_pair &dimTags, const double size);
+
+        // Sets a transfinite meshing constraint on the line `tag', with
+        // `numVertices' mesh vertices distributed according to `type' and
+        // `coef'. Currently supported types are "Progression" (geometrical
+        // progression with power `coef') and "Bump" (refinement toward both
+        // extreminties of the line).
+        GMSH_API void setTransfiniteLine(const int tag, const int nPoints,
+                                         const std::string &type = "Progression",
+                                         const double coef = 1.);
+
+        // Sets a transfinite meshing constraint on the surface
+        // `tag'. `arrangement' describes the arrangement of the triangles when
+        // the surface is not flagged as recombined: currently supported values
+        // are "Left", "Right", "AlternateLeft" and
+        // "AlternateRight". `cornerTags' can be used to specify the (3 or 4)
+        // corners of the transfinite interpolation explicitly; specifying the
+        // corners explicitly is mandatory if the surface has more that 3 or 4
+        // points on its boundary.
+        GMSH_API void setTransfiniteSurface(const int tag,
+                                            const std::string &arrangement = "Left",
+                                            const std::vector<int> &cornerTags =
+                                            std::vector<int>());
+
+        // Sets a transfinite meshing constraint on the surface
+        // `tag'. `cornerTags' can be used to specify the (6 or 8) corners of the
+        // transfinite interpolation explicitly.
+        GMSH_API void setTransfiniteVolume(const int tag,
+                                           const std::vector<int> &cornerTags =
+                                           std::vector<int>());
+
+        // Sets a recombination meshing constraint on the geometrical entity of
+        // dimension `dim' and tag `tag'. Currently only entities of dimension 2
+        // (to recombine triangles into quadrangles) are supported.
+        GMSH_API void setRecombine(const int dim, const int tag,
+                                   const double angle = 45.);
+
+        // Sets a smoothing meshing constraint on the geometrical entity of
+        // dimension `dim' and tag `tag'. `val' iterations of a Laplace smoother
+        // are applied.
+        GMSH_API void setSmoothing(const int dim, const int tag,
+                                   const int val);
+
+        // Sets a reverse meshing constraint on the geometrical entity of
+        // dimension `dim' and tag `tag'. If `val' is true, the mesh orientation
+        // will be reversed with respect to the natural mesh orientation (i.e. the
+        // orientation consistent with the orientation of the geometrical
+        // entity). If `val' is false, the mesh is left as-is.
+        GMSH_API void setReverse(const int dim, const int tag,
+                                 const bool val = true);
+
+      } // namespace mesh
+
+    } // namespace geo
+
+    namespace occ { // Internal per-model OpenCASCADE CAD kernel functions
+
+      // Adds a geometrical point in the internal OpenCASCADE CAD
+      // representation, at coordinates (x, y, z). If `meshSize' is > 0, adds a
+      // meshing constraint at that point. If `tag' is positive, sets the tag
+      // explicitly; otherwise a new tag is selected automatically. Returns the
+      // tag of the point. (Note that the point will be added in the current
+      // model only after gmshModelGeoSynchronize() is called. This behavior
+      // holds for all the entities added in the gmshModelOcc module.)
+      GMSH_API int addPoint(const double x, const double y, const double z,
+                            const double meshSize = 0., const int tag = -1);
+
+      // Adds a straight line segment between the two points with tags
+      // `startTag' and `endTag'. If `tag' is positive, sets the tag explicitly;
+      // otherwise a new tag is selected automatically. Returns the tag of the
+      // line.
+      GMSH_API int addLine(const int startTag, const int endTag,
+                           const int tag = -1);
+
+      // Adds a circle arc between the two points with tags `startTag' and
+      // `endTag', with center `centertag'. If `tag' is positive, sets the tag
+      // explicitly; otherwise a new tag is selected automatically. Returns the
+      // tag of the circle arc.
+      GMSH_API int addCircleArc(const int startTag, const int centerTag,
+                                const int endTag, const int tag = -1);
+
+      // Adds a circle of center (`x', `y', `z') and radius `r'. If `tag' is
+      // positive, sets the tag explicitly; otherwise a new tag is selected
+      // automatically. `angle1' and `angle2' allow to add a circle
+      // arc. Returns the tag of the circle.
+      GMSH_API int addCircle(const double x, const double y, const double z,
+                             const double r, const int tag = -1,
+                             const double angle1 = 0.,
+                             const double angle2 = 2*M_PI);
+
+      GMSH_API int addEllipseArc(const int startTag, const int centerTag,
+                                             const int endTag, const int tag = -1);
+      GMSH_API int addEllipse(const double x, const double y, const double z,
+                              const double r1, const double r2,
+                              const int tag = -1,
+                              const double angle1 = 0.,
+                              const double angle2 = 2*M_PI);
+      GMSH_API int addSpline(const std::vector<int> &vertexTags,
+                             const int tag = -1);
+      GMSH_API int addBezier(const std::vector<int> &vertexTags,
+                             const int tag = -1);
+      GMSH_API int addBSpline(const std::vector<int> &vertexTags,
+                              const int tag = -1);
+      GMSH_API int addWire(const std::vector<int> &edgeTags,
+                           const int tag = -1,
+                           const bool checkClosed = false);
+      GMSH_API int addLineLoop(const std::vector<int> &edgeTags,
+                               const int tag = -1);
+      GMSH_API int addRectangle(const double x, const double y,
+                                const double z, const double dx,
+                                const double dy,
+                                const int tag = -1,
+                                const double roundedRadius = 0.);
+      GMSH_API int addDisk(const double xc, const double yc,
+                           const double zc, const double rx,
+                           const double ry, const int tag = -1);
+      GMSH_API int addPlaneSurface(const std::vector<int> &wireTags,
                                    const int tag = -1);
-GMSH_API int gmshModelOccAddSphere(const double xc, const double yc,
-                                   const double zc, const double radius,
+      GMSH_API int addSurfaceFilling(int wireTag, const int tag = -1);
+      GMSH_API int addSurfaceLoop(const std::vector<int> &faceTags,
+                                  const int tag = -1);
+      GMSH_API int addVolume(const std::vector<int> &shellTags,
+                             const int tag = -1);
+      GMSH_API int addSphere(const double xc, const double yc,
+                             const double zc, const double radius,
+                             const int tag = -1,
+                             const double angle1 = -M_PI/2,
+                             const double angle2 = M_PI/2,
+                             const double angle3 = 2*M_PI);
+      GMSH_API int addBox(const double x, const double y, const double z,
+                          const double dx, const double dy, const double dz,
+                          const int tag = -1);
+      GMSH_API int addCylinder(const double x, const double y,
+                               const double z, const double dx,
+                               const double dy, const double dz,
+                               const double r, const int tag = -1,
+                               double angle = 2*M_PI);
+      GMSH_API int addCone(const double x, const double y, const double z,
+                           const double dx, const double dy, const double dz,
+                           const double r1, const double r2,
+                           const int tag = -1,
+                           const double angle = 2*M_PI);
+      GMSH_API int addWedge(const double x, const double y, const double z,
+                            const double dx, const double dy, const double dz,
+                            const int tag = -1, const double ltx = 0.);
+      GMSH_API int addTorus(const double x, const double y, const double z,
+                            const double r1, const double r2,
+                            const int tag = -1,
+                            const double angle = 2*M_PI);
+      GMSH_API int addThruSections(const std::vector<int> &wireTags,
+                                   vector_pair &outDimTags,
                                    const int tag = -1,
-                                   const double angle1 = -M_PI/2,
-                                   const double angle2 = M_PI/2,
-                                   const double angle3 = 2*M_PI);
-GMSH_API int gmshModelOccAddBox(const double x, const double y, const double z,
-                                const double dx, const double dy, const double dz,
-                                const int tag = -1);
-GMSH_API int gmshModelOccAddCylinder(const double x, const double y,
-                                     const double z, const double dx,
-                                     const double dy, const double dz,
-                                     const double r, const int tag = -1,
-                                     double angle = 2*M_PI);
-GMSH_API int gmshModelOccAddCone(const double x, const double y, const double z,
-                                 const double dx, const double dy, const double dz,
-                                 const double r1, const double r2,
-                                 const int tag = -1,
-                                 const double angle = 2*M_PI);
-GMSH_API int gmshModelOccAddWedge(const double x, const double y, const double z,
-                                  const double dx, const double dy, const double dz,
-                                  const int tag = -1, const double ltx = 0.);
-GMSH_API int gmshModelOccAddTorus(const double x, const double y, const double z,
-                                  const double r1, const double r2,
-                                  const int tag = -1,
-                                  const double angle = 2*M_PI);
-GMSH_API int gmshModelOccAddThruSections(const std::vector<int> &wireTags,
-                                         vector_pair &outDimTags,
-                                         const int tag = -1,
-                                         const bool makeSolid = true,
-                                         const bool makeRuled = false);
-GMSH_API int addThickSolid(const int solidTag,
-                           const std::vector<int> &excludeFaceTags,
-                           const double offset, vector_pair &outDimTags,
-                           const int tag = -1);
-GMSH_API void gmshModelOccExtrude(const vector_pair &dimTags, const double dx,
-                                  const double dy, const double dz,
-                                  vector_pair &outDimTags,
-                                  const std::vector<int> &numElements =
-                                  std::vector<int>(),
-                                  const std::vector<double> &heights =
-                                  std::vector<double>(),
-                                  const bool recombine = false);
-GMSH_API void gmshModelOccRevolve(const vector_pair &dimTags,
-                                  const double x, const double y, const double z,
-                                  const double ax, const double ay, const double az,
-                                  const double angle, vector_pair &outDimTags,
-                                  const std::vector<int> &numElements =
-                                  std::vector<int>(),
-                                  const std::vector<double> &heights =
-                                  std::vector<double>(),
-                                  const bool recombine = false);
-GMSH_API void gmshModelOccAddPipe(const vector_pair &dimTags, int wireTag,
-                                  vector_pair &outDimTags);
-GMSH_API void gmshModelOccFillet(const std::vector<int> &regionTags,
-                                 const std::vector<int> &edgeTags,
-                                 const double radius, vector_pair &outDimTags,
-                                 const bool removeRegion = true);
-GMSH_API int gmshModelOccBooleanUnion(const vector_pair &objectDimTags,
-                                      const vector_pair &toolDimTags,
-                                      vector_pair &outDimTags,
-                                      std::vector<vector_pair> &outDimTagsMap,
-                                      const int tag = -1,
-                                      const bool removeObject = true,
-                                      const bool removeTool = true);
-GMSH_API int gmshModelOccBooleanIntersection(const vector_pair &objectDimTags,
-                                             const vector_pair &toolDimTags,
-                                             vector_pair &outDimTags,
-                                             std::vector<vector_pair > &outDimTagsMap,
-                                             const int tag = -1,
-                                             const bool removeObject = true,
-                                             const bool removeTool = true);
-GMSH_API int gmshModelOccBooleanDifference(const vector_pair &objectDimTags,
-                                           const vector_pair &toolDimTags,
-                                           vector_pair &outDimTags,
-                                           std::vector<vector_pair > &outDimTagsMap,
-                                           const int tag = -1,
-                                           const bool removeObject = true,
-                                           const bool removeTool = true);
-GMSH_API int gmshModelOccBooleanFragments(const vector_pair &objectDimTags,
-                                          const vector_pair &toolDimTags,
-                                          vector_pair &outDimTags,
-                                          std::vector<vector_pair> &outDimTagsMap,
-                                          const int tag = -1,
-                                          const bool removeObject = true,
-                                          const bool removeTool = true);
-GMSH_API void gmshModelOccTranslate(const vector_pair &dimTags, const double dx,
-                                    const double dy, const double dz);
-GMSH_API void gmshModelOccRotate(const vector_pair &dimTags, const double x,
-                                 const double y, const double z, const double ax,
-                                 const double ay, const double az, const double angle);
-GMSH_API void gmshModelOccDilate(const vector_pair &dimTags, const double x,
-                                 const double y, const double z, const double a,
-                                 const double b, const double c);
-GMSH_API void gmshModelOccSymmetry(const vector_pair &dimTags, const double a,
-                                   const double b, const double c, const double d);
-GMSH_API void gmshModelOccCopy(const vector_pair &dimTags, vector_pair &outDimTags);
-GMSH_API void gmshModelOccRemove(const vector_pair &dimTags,
-                                 const bool recursive = false);
-GMSH_API void gmshModelOccRemoveAllDuplicates();
-GMSH_API void gmshModelOccImportShapes(const std::string &fileName,
+                                   const bool makeSolid = true,
+                                   const bool makeRuled = false);
+      GMSH_API int addThickSolid(const int solidTag,
+                                 const std::vector<int> &excludeFaceTags,
+                                 const double offset, vector_pair &outDimTags,
+                                 const int tag = -1);
+      GMSH_API void extrude(const vector_pair &dimTags, const double dx,
+                            const double dy, const double dz,
+                            vector_pair &outDimTags,
+                            const std::vector<int> &numElements =
+                            std::vector<int>(),
+                            const std::vector<double> &heights =
+                            std::vector<double>(),
+                            const bool recombine = false);
+      GMSH_API void revolve(const vector_pair &dimTags,
+                            const double x, const double y, const double z,
+                            const double ax, const double ay, const double az,
+                            const double angle, vector_pair &outDimTags,
+                            const std::vector<int> &numElements =
+                            std::vector<int>(),
+                            const std::vector<double> &heights =
+                            std::vector<double>(),
+                            const bool recombine = false);
+      GMSH_API void addPipe(const vector_pair &dimTags, int wireTag,
+                            vector_pair &outDimTags);
+      GMSH_API void fillet(const std::vector<int> &regionTags,
+                           const std::vector<int> &edgeTags,
+                           const double radius, vector_pair &outDimTags,
+                           const bool removeRegion = true);
+      GMSH_API int booleanUnion(const vector_pair &objectDimTags,
+                                const vector_pair &toolDimTags,
+                                vector_pair &outDimTags,
+                                std::vector<vector_pair> &outDimTagsMap,
+                                const int tag = -1,
+                                const bool removeObject = true,
+                                const bool removeTool = true);
+      GMSH_API int booleanIntersection(const vector_pair &objectDimTags,
+                                       const vector_pair &toolDimTags,
                                        vector_pair &outDimTags,
-                                       const bool highestDimOnly = true,
-                                       const std::string &format = "");
-GMSH_API void gmshModelOccSetMeshSize(const vector_pair &dimTags, const double size);
-GMSH_API void gmshModelOccSynchronize();
-
-// -----------------------------------------------------------------------------
-// Section "gmshModelField": mesh size field functions for current model
-// -----------------------------------------------------------------------------
-
-GMSH_API int gmshModelFieldCreate(const std::string &type, const int tag = -1);
-GMSH_API void gmshModelFieldDelete(const int tag);
-GMSH_API void gmshModelFieldSetNumber(const int tag, const std::string &option,
-                                      const double value);
-GMSH_API void gmshModelFieldSetString(const int tag, const std::string &option,
-                                      const std::string &value);
-GMSH_API void gmshModelFieldSetNumbers(const int tag, const std::string &option,
-                                       const std::vector<double> &value);
-GMSH_API void gmshModelFieldSetAsBackground(const int tag);
+                                       std::vector<vector_pair> &outDimTagsMap,
+                                       const int tag = -1,
+                                       const bool removeObject = true,
+                                       const bool removeTool = true);
+      GMSH_API int booleanDifference(const vector_pair &objectDimTags,
+                                     const vector_pair &toolDimTags,
+                                     vector_pair &outDimTags,
+                                     std::vector<vector_pair> &outDimTagsMap,
+                                     const int tag = -1,
+                                     const bool removeObject = true,
+                                     const bool removeTool = true);
+      GMSH_API int booleanFragments(const vector_pair &objectDimTags,
+                                    const vector_pair &toolDimTags,
+                                    vector_pair &outDimTags,
+                                    std::vector<vector_pair> &outDimTagsMap,
+                                    const int tag = -1,
+                                    const bool removeObject = true,
+                                    const bool removeTool = true);
+      GMSH_API void translate(const vector_pair &dimTags, const double dx,
+                              const double dy, const double dz);
+      GMSH_API void rotate(const vector_pair &dimTags, const double x,
+                           const double y, const double z, const double ax,
+                           const double ay, const double az, const double angle);
+      GMSH_API void dilate(const vector_pair &dimTags, const double x,
+                           const double y, const double z, const double a,
+                           const double b, const double c);
+      GMSH_API void symmetry(const vector_pair &dimTags, const double a,
+                             const double b, const double c, const double d);
+      GMSH_API void copy(const vector_pair &dimTags, vector_pair &outDimTags);
+      GMSH_API void remove(const vector_pair &dimTags,
+                           const bool recursive = false);
+      GMSH_API void removeAllDuplicates();
+      GMSH_API void importShapes(const std::string &fileName,
+                                 vector_pair &outDimTags,
+                                 const bool highestDimOnly = true,
+                                 const std::string &format = "");
+
+      // Sets a mesh size constraint on the geometrical entities
+      // `dimTags'. Currently only entities of dimension 0 (points) are handled.
+      GMSH_API void setMeshSize(const vector_pair &dimTags, const double size);
+
+      // Synchronize the internal OpenCASCADE CAD representation with the
+      // current Gmsh model. This can be called at any time, but since it
+      // involves a non trivial amount of processing, the number of
+      // synchronization points should normally be minimized.
+      GMSH_API void synchronize();
+
+    } // namespace occ
+
+  } // namespace model
+
+  namespace view { // Post-processing view functions
+
+    // Adds a new post-processing view, with name `name'. If `tag' is positive
+    // use it (and remove the view with that tag if it already exists),
+    // otherwise associate a new tag. Returns the view tag.
+    GMSH_API int add(const std::string &name, const int tag = -1);
+
+    // Removes the view with tag `tag'.
+    GMSH_API void remove(const int tag);
+
+    // Gets the index of the view with tag `tag' in the list of currently loaded
+    // views. This dynamic index (it can change when views are removed) is used
+    // to access view options with the gmshOption functions.
+    GMSH_API int getIndex(const int tag);
+
+    // Gets the tags of all views.
+    GMSH_API void getTags(std::vector<int> &tags);
+
+    // Adds model-based post-processing data to the view with tag
+    // `tag'. `modelName' identifies the model the data is attached
+    // to. `dataType' specifies the type of data, currently either "NodeData",
+    // "ElementData" or "ElementNodeData". `tags' gives the tags of the vertices
+    // or elements in the mesh to which the data is associated. `data' is a
+    // vector of length `tags.size()`: each entry is the vector of double
+    // precision numbers representing the data associated with the corresponding
+    // tag. The optional `step` and `time` arguments associate a time step and
+    // time value with the data. `numComponents' gives the number of data
+    // components (1 for scalar data, 3 for vector data, etc.) per entity; if
+    // negative, it is automatically inferred (when possible) from the input
+    // data. `partition' allows to specify data in several sub-sets.
+    GMSH_API void addModelData(const int tag, const std::string &modelName,
+                               const std::string &dataType,
+                               const std::vector<int> &tags,
+                               const std::vector<std::vector<double> > &data,
+                               const int step = 0, const int time = 0.,
+                               const int numComponents = -1,
+                               const int partition = 0);
+
+    // Adds list-based post-processing data to the view with tag `tag'. `type'
+    // identifies the data: "SP" for scalar points, "VP", for vector points,
+    // etc. `numEle' gives the number of elements in the data. `data' contains
+    // the data for the `numEle' elements.
+    GMSH_API void addListData(const int tag, const std::string &type,
+                              const int numEle, const std::vector<double> &data);
+
+    // Probes the view `tag' for its `value' at point (`x', `y', `z').
+    GMSH_API void probe(const int tag, const double x, const double y,
+                        const double z, std::vector<double> &value,
+                        const int step = -1, const int numComp = -1,
+                        const bool gradient = false,
+                        const double tolerance = 0.,
+                        const std::vector<double> xElemCoord
+                        = std::vector<double>(),
+                        const std::vector<double> yElemCoord
+                        = std::vector<double>(),
+                        const std::vector<double> zElemCoord
+                        = std::vector<double>());
+
+    // Writes the view to a file. The export format is determined by the file
+    // extension.
+    GMSH_API void write(const int tag, const std::string &fileName,
+                        const bool append = false);
+
+  } // namespace view
+
+  namespace plugin { // Plugin functions
+
+    // Sets the numerical option `option` to the value `value' for plugin `name'.
+    GMSH_API void setNumber(const std::string &name,
+                            const std::string &option,
+                            const double value);
+
+    // Sets the string option `option` to the value `value' for plugin `name'.
+    GMSH_API void setString(const std::string &name,
+                            const std::string &option,
+                            const std::string &value);
+
+    // Runs the plugin `name'.
+    GMSH_API void run(const std::string &name);
+
+  } // namespace plugin
+
+} // namespace gmsh
 
 #undef GMSH_API
 
diff --git a/Common/gmsh.i b/Common/gmsh.i
index e74857288b0f40fdda50a027b0d202b65c39ac4d..1a3cb6d9b0e4f5b6bf9124e7bb680c0fa4e7daa6 100644
--- a/Common/gmsh.i
+++ b/Common/gmsh.i
@@ -16,8 +16,142 @@
 %template(IntVector) std::vector<int>;
 %template(IntVectorVector) std::vector<std::vector<int> >;
 %template(DoubleVector) std::vector<double>;
+%template(DoubleVectorVector) std::vector<std::vector<double> >;
 %template(StringVector) std::vector<std::string>;
 %template(PairVector) std::vector<std::pair<int, int> >;
 %template(PairVectorVector) std::vector<std::vector<std::pair<int, int> > >;
 
+%rename(initialize)                         gmsh::initialize;
+%rename(finalize)                           gmsh::finalize;
+%rename(open)                               gmsh::open;
+%rename(merge)                              gmsh::merge;
+%rename(write)                              gmsh::write;
+%rename(clear)                              gmsh::clear;
+%rename(optionSetNumber)                    gmsh::option::setNumber;
+%rename(optionGetNumber)                    gmsh::option::getNumber;
+%rename(optionSetString)                    gmsh::option::setString;
+%rename(optionGetString)                    gmsh::option::getString;
+%rename(modelAdd)                           gmsh::model::add;
+%rename(modelRemove)                        gmsh::model::remove;
+%rename(modelList)                          gmsh::model::list;
+%rename(modelSetCurrent)                    gmsh::model::setCurrent;
+%rename(modelGetEntities)                   gmsh::model::getEntities;
+%rename(modelGetPhysicalGroups)             gmsh::model::getPhysicalGroups;
+%rename(modelGetEntitiesForPhysicalGroup)   gmsh::model::getEntitiesForPhysicalGroup;
+%rename(modelAddPhysicalGroup)              gmsh::model::addPhysicalGroup;
+%rename(modelSetPhysicalName)               gmsh::model::setPhysicalName;
+%rename(modelGetPhysicalName)               gmsh::model::getPhysicalName;
+%rename(modelGetBoundary)                   gmsh::model::getBoundary;
+%rename(modelGetEntitiesInBoundingBox)      gmsh::model::getEntitiesInBoundingBox;
+%rename(modelGetBoundingBox)                gmsh::model::getBoundingBox;
+%rename(modelAddDiscreteEntity)             gmsh::model::addDiscreteEntity;
+%rename(modelRemoveEntities)                gmsh::model::removeEntities;
+%rename(modelMeshGenerate)                  gmsh::model::mesh::generate;
+%rename(modelMeshGetLastEntityError)        gmsh::model::mesh::getLastEntityError;
+%rename(modelMeshGetLastVertexError)        gmsh::model::mesh::getLastVertexError;
+%rename(modelMeshGetVertices)               gmsh::model::mesh::getVertices;
+%rename(modelMeshGetElements)               gmsh::model::mesh::getElements;
+%rename(modelMeshSetVertices)               gmsh::model::mesh::setVertices;
+%rename(modelMeshSetElements)               gmsh::model::mesh::setElements;
+%rename(modelMeshGetVertex)                 gmsh::model::mesh::getVertex;
+%rename(modelMeshGetElement)                gmsh::model::mesh::getElement;
+%rename(modelMeshSetSize)                   gmsh::model::mesh::setSize;
+%rename(modelMeshSetTransfiniteLine)        gmsh::model::mesh::setTransfiniteLine;
+%rename(modelMeshSetTransfiniteSurface)     gmsh::model::mesh::setTransfiniteSurface;
+%rename(modelMeshSetTransfiniteVolume)      gmsh::model::mesh::setTransfiniteVolume;
+%rename(modelMeshSetRecombine)              gmsh::model::mesh::setRecombine;
+%rename(modelMeshSetSmoothing)              gmsh::model::mesh::setSmoothing;
+%rename(modelMeshSetReverse)                gmsh::model::mesh::setReverse;
+%rename(modelMeshEmbed)                     gmsh::model::mesh::embed;
+%rename(modelMeshFieldAdd)                  gmsh::model::mesh::field::add;
+%rename(modelMeshFieldRemove)               gmsh::model::mesh::field::remove;
+%rename(modelMeshFieldSetNumber)            gmsh::model::mesh::field::setNumber;
+%rename(modelMeshFieldSetString)            gmsh::model::mesh::field::setString;
+%rename(modelMeshFieldSetNumbers)           gmsh::model::mesh::field::setNumbers;
+%rename(modelMeshFieldSetAsBackground)      gmsh::model::mesh::field::setAsBackground;
+%rename(modelGeoAddPoint)                   gmsh::model::geo::addPoint;
+%rename(modelGeoAddLine)                    gmsh::model::geo::addLine;
+%rename(modelGeoAddCircleArc)               gmsh::model::geo::addCircleArc;
+%rename(modelGeoAddEllipseArc)              gmsh::model::geo::addEllipseArc;
+%rename(modelGeoAddSpline)                  gmsh::model::geo::addSpline;
+%rename(modelGeoAddBSpline)                 gmsh::model::geo::addBSpline;
+%rename(modelGeoAddBezier)                  gmsh::model::geo::addBezier;
+%rename(modelGeoAddLineLoop)                gmsh::model::geo::addLineLoop;
+%rename(modelGeoAddPlaneSurface)            gmsh::model::geo::addPlaneSurface;
+%rename(modelGeoAddSurfaceFilling)          gmsh::model::geo::addSurfaceFilling;
+%rename(modelGeoAddSurfaceLoop)             gmsh::model::geo::addSurfaceLoop;
+%rename(modelGeoAddVolume)                  gmsh::model::geo::addVolume;
+%rename(modelGeoExtrude)                    gmsh::model::geo::extrude;
+%rename(modelGeoRevolve)                    gmsh::model::geo::revolve;
+%rename(modelGeoTwist)                      gmsh::model::geo::twist;
+%rename(modelGeoTranslate)                  gmsh::model::geo::translate;
+%rename(modelGeoRotate)                     gmsh::model::geo::rotate;
+%rename(modelGeoDilate)                     gmsh::model::geo::dilate;
+%rename(modelGeoSymmetry)                   gmsh::model::geo::symmetry;
+%rename(modelGeoCopy)                       gmsh::model::geo::copy;
+%rename(modelGeoRemove)                     gmsh::model::geo::remove;
+%rename(modelGeoRemoveAllDuplicates)        gmsh::model::geo::removeAllDuplicates;
+%rename(modelGeoSynchronize)                gmsh::model::geo::synchronize;
+%rename(modelGeoMeshSetTransfiniteLine)     gmsh::model::geo::mesh::setTransfiniteLine;
+%rename(modelGeoMeshSetTransfiniteSurface)  gmsh::model::geo::mesh::setTransfiniteSurface;
+%rename(modelGeoMeshSetTransfiniteVolume)   gmsh::model::geo::mesh::setTransfiniteVolume;
+%rename(modelGeoMeshSetRecombine)           gmsh::model::geo::mesh::setRecombine;
+%rename(modelGeoMeshSetSmoothing)           gmsh::model::geo::mesh::setSmoothing;
+%rename(modelGeoMeshSetReverse)             gmsh::model::geo::mesh::setReverse;
+%rename(modelGeoMeshSetSize)                gmsh::model::geo::mesh::setSize;
+%rename(modelOccAddPoint)                   gmsh::model::occ::addPoint;
+%rename(modelOccAddLine)                    gmsh::model::occ::addLine;
+%rename(modelOccAddCircleArc)               gmsh::model::occ::addCircleArc;
+%rename(modelOccAddCircle)                  gmsh::model::occ::addCircle;
+%rename(modelOccAddEllipseArc)              gmsh::model::occ::addEllipseArc;
+%rename(modelOccAddEllipse)                 gmsh::model::occ::addEllipse;
+%rename(modelOccAddSpline)                  gmsh::model::occ::addSpline;
+%rename(modelOccAddBezier)                  gmsh::model::occ::addBezier;
+%rename(modelOccAddBSpline)                 gmsh::model::occ::addBSpline;
+%rename(modelOccAddWire)                    gmsh::model::occ::addWire;
+%rename(modelOccAddLineLoop)                gmsh::model::occ::addLineLoop;
+%rename(modelOccAddRectangle)               gmsh::model::occ::addRectangle;
+%rename(modelOccAddDisk)                    gmsh::model::occ::addDisk;
+%rename(modelOccAddPlaneSurface)            gmsh::model::occ::addPlaneSurface;
+%rename(modelOccAddSurfaceFilling)          gmsh::model::occ::addSurfaceFilling;
+%rename(modelOccAddSurfaceLoop)             gmsh::model::occ::addSurfaceLoop;
+%rename(modelOccAddVolume)                  gmsh::model::occ::addVolume;
+%rename(modelOccAddSphere)                  gmsh::model::occ::addSphere;
+%rename(modelOccAddBox)                     gmsh::model::occ::addBox;
+%rename(modelOccAddCylinder)                gmsh::model::occ::addCylinder;
+%rename(modelOccAddCone)                    gmsh::model::occ::addCone;
+%rename(modelOccAddWedge)                   gmsh::model::occ::addWedge;
+%rename(modelOccAddTorus)                   gmsh::model::occ::addTorus;
+%rename(modelOccAddThruSections)            gmsh::model::occ::addThruSections;
+%rename(modelOccAddThickSolid)              gmsh::model::occ::addThickSolid;
+%rename(modelOccExtrude)                    gmsh::model::occ::extrude;
+%rename(modelOccRevolve)                    gmsh::model::occ::revolve;
+%rename(modelOccAddPipe)                    gmsh::model::occ::addPipe;
+%rename(modelOccFillet)                     gmsh::model::occ::fillet;
+%rename(modelOccBooleanUnion)               gmsh::model::occ::booleanUnion;
+%rename(modelOccBooleanIntersection)        gmsh::model::occ::booleanIntersection;
+%rename(modelOccBooleanDifference)          gmsh::model::occ::booleanDifference;
+%rename(modelOccBooleanFragments)           gmsh::model::occ::booleanFragments;
+%rename(modelOccTranslate)                  gmsh::model::occ::translate;
+%rename(modelOccRotate)                     gmsh::model::occ::rotate;
+%rename(modelOccDilate)                     gmsh::model::occ::dilate;
+%rename(modelOccSymmetry)                   gmsh::model::occ::symmetry;
+%rename(modelOccCopy)                       gmsh::model::occ::copy;
+%rename(modelOccRemove)                     gmsh::model::occ::remove;
+%rename(modelOccRemoveAllDuplicates)        gmsh::model::occ::removeAllDuplicates;
+%rename(modelOccImportShapes)               gmsh::model::occ::importShapes;
+%rename(modelOccSetMeshSize)                gmsh::model::occ::setMeshSize;
+%rename(modelOccSynchronize)                gmsh::model::occ::synchronize;
+%rename(viewAdd)                            gmsh::view::add;
+%rename(viewRemove)                         gmsh::view::remove;
+%rename(viewGetIndex)                       gmsh::view::getIndex;
+%rename(viewGetTags)                        gmsh::view::getTags;
+%rename(viewAddModelData)                   gmsh::view::addModelData;
+%rename(viewAddListData)                    gmsh::view::addListData;
+%rename(viewProbe)                          gmsh::view::probe;
+%rename(viewWrite)                          gmsh::view::write;
+%rename(pluginSetNumber)                    gmsh::plugin::setNumber;
+%rename(pluginSetString)                    gmsh::plugin::setString;
+%rename(pluginRun)                          gmsh::plugin::run;
+
 %include "gmsh.h"
diff --git a/Plugin/Levelset.cpp b/Plugin/Levelset.cpp
index 6b1830f9f72bdc17c8ed94ee8579895557317da5..9ae408015803635ed67d8d68f8a2614186981452 100644
--- a/Plugin/Levelset.cpp
+++ b/Plugin/Levelset.cpp
@@ -466,8 +466,7 @@ PView *GMSH_LevelsetPlugin::execute(PView *v)
   double scalarValues[8] = {0., 0., 0., 0., 0., 0., 0., 0.};
 
   if(_valueIndependent) {
-    // create a single output view containing the (possibly
-    // multi-step) levelset
+    // create a single output view containing the (possibly multi-step) levelset
     int firstNonEmptyStep = vdata->getFirstNonEmptyTimeStep();
     PViewDataList *out = getDataList(new PView());
     for(int ent = 0; ent < vdata->getNumEntities(firstNonEmptyStep); ent++){
diff --git a/Post/PView.cpp b/Post/PView.cpp
index 51705e00fc668b265c8c4252ef3e978c3f38b15d..ac81e79b5a8258629bfb7bc6af5379464109a1fb 100644
--- a/Post/PView.cpp
+++ b/Post/PView.cpp
@@ -152,7 +152,7 @@ PView::PView(const std::string &name, const std::string &type,
                             _options->targetError);
 }
 
-void PView::addStep(GModel *model, std::map<int, std::vector<double> > &data,
+void PView::addStep(GModel *model, const std::map<int, std::vector<double> > &data,
                     double time, int numComp)
 {
   PViewDataGModel *d = dynamic_cast<PViewDataGModel*>(_data);
diff --git a/Post/PView.h b/Post/PView.h
index 7113b495f00d778bdd110b148e341591ff234a17..3d5ab8cb0b9f7ad0f73de108ecf25353717ea171 100644
--- a/Post/PView.h
+++ b/Post/PView.h
@@ -58,7 +58,7 @@ class PView{
         std::map<int, std::vector<double> > &data, double time=0.,
         int numComp = -1);
   // add a new time step to a given mesh-based view
-  void addStep(GModel *model, std::map<int, std::vector<double> > &data,
+  void addStep(GModel *model, const std::map<int, std::vector<double> > &data,
                double time=0.,int numComp = -1);
 
   // default destructor
diff --git a/Post/PViewDataGModel.h b/Post/PViewDataGModel.h
index e7af95139500bead32179a85452d754982864b39..78fb958d2b7e4c2f6558e1e64045a45f8932873f 100644
--- a/Post/PViewDataGModel.h
+++ b/Post/PViewDataGModel.h
@@ -34,6 +34,9 @@ class stepData{
   // optimal. This is the price to pay if we want 1) rapid access to
   // the data and 2) not to store any additional info in MVertex or
   // MElement)
+  //
+  // FIXME: we should change this design and store a vector<int> of tags, and do
+  // indirect addressing, even if it's a bit slower...
   std::vector<Real*> *_data;
   // a vector containing the multiplying factor allowing to compute
   // the number of values stored in _data for each index (number of
@@ -242,7 +245,12 @@ class PViewDataGModel : public PViewData {
 
   // Add some data "on the fly" (data is stored in a map, indexed by
   // node or element number depending on the type of dataset)
-  bool addData(GModel *model, std::map<int, std::vector<double> > &data,
+  bool addData(GModel *model, const std::map<int, std::vector<double> > &data,
+               int step, double time, int partition, int numComp);
+
+  // Add some data "on the fly", without a map
+  bool addData(GModel *model, const std::vector<int> &tags,
+               const std::vector<std::vector<double> > &data,
                int step, double time, int partition, int numComp);
 
   // Allow to destroy the data
@@ -252,8 +260,8 @@ class PViewDataGModel : public PViewData {
                int fileIndex, FILE *fp, bool binary, bool swap, int step,
                double time, int partition, int numComp, int numNodes,
                const std::string &interpolationScheme);
-  virtual bool writeMSH(const std::string &fileName, double version=2.2, bool binary=false,
-                        bool savemesh=true, bool multipleView=false,
+  virtual bool writeMSH(const std::string &fileName, double version=2.2,
+                        bool binary=false, bool savemesh=true, bool multipleView=false,
                         int partitionNum=0, bool saveInterpolationMatrices=true,
                         bool forceNodeData=false, bool forceElementData=false);
   bool readMED(const std::string &fileName, int fileIndex);
diff --git a/Post/PViewDataGModelIO.cpp b/Post/PViewDataGModelIO.cpp
index fd6ee713dd85b2761fce0405546bd19bcb083835..70827db45fd6c421dcbc1143b98e06d09066be93 100644
--- a/Post/PViewDataGModelIO.cpp
+++ b/Post/PViewDataGModelIO.cpp
@@ -12,14 +12,15 @@
 #include "StringUtils.h"
 #include "OS.h"
 
-bool PViewDataGModel::addData(GModel *model, std::map<int, std::vector<double> > &data,
+bool PViewDataGModel::addData(GModel *model,
+                              const std::map<int, std::vector<double> > &data,
                               int step, double time, int partition, int numComp)
 {
   if(data.empty()) return false;
 
   if (numComp < 0){
     numComp = 9;
-    for(std::map<int, std::vector<double> >::iterator it = data.begin();
+    for(std::map<int, std::vector<double> >::const_iterator it = data.begin();
         it != data.end(); it++)
       numComp = std::min(numComp, (int)it->second.size());
   }
@@ -34,7 +35,7 @@ bool PViewDataGModel::addData(GModel *model, std::map<int, std::vector<double> >
     model->getNumMeshElements();
   _steps[step]->resizeData(numEnt);
 
-  for(std::map<int, std::vector<double> >::iterator it = data.begin();
+  for(std::map<int, std::vector<double> >::const_iterator it = data.begin();
       it != data.end(); it++){
     int mult = it->second.size() / numComp;
     double *d  = _steps[step]->getData(it->first, true, mult);
@@ -47,6 +48,41 @@ bool PViewDataGModel::addData(GModel *model, std::map<int, std::vector<double> >
   return true;
 }
 
+bool PViewDataGModel::addData(GModel *model,
+                              const std::vector<int> &tags,
+                              const std::vector<std::vector<double> > &data,
+                              int step, double time, int partition, int numComp)
+{
+  if(data.empty() || tags.empty() || data.size() != tags.size()) return false;
+
+  if (numComp < 0){
+    numComp = 9;
+    for(unsigned int i = 0; i < data.size(); i++)
+       numComp = std::min(numComp, (int)data[i].size());
+  }
+
+  while(step >= (int)_steps.size())
+    _steps.push_back(new stepData<double>(model, numComp));
+  _steps[step]->fillEntities();
+  _steps[step]->computeBoundingBox();
+  _steps[step]->setTime(time);
+
+  int numEnt = (_type == NodeData) ? model->getNumMeshVertices() :
+    model->getNumMeshElements();
+  _steps[step]->resizeData(numEnt);
+
+  for(unsigned int i = 0; i < data.size(); i++){
+    int mult = data[i].size() / numComp;
+    double *d  = _steps[step]->getData(tags[i], true, mult);
+    for(int j = 0; j < numComp * mult; j++)
+      d[j] = data[i][j];
+  }
+  if(partition >= 0)
+    _steps[step]->getPartitions().insert(partition);
+  finalize();
+  return true;
+}
+
 void PViewDataGModel::destroyData()
 {
   for(unsigned int i = 0; i < _steps.size(); i++)
diff --git a/Post/PViewDataList.h b/Post/PViewDataList.h
index 39e62626823afc33e2cc40ed955710d8e078da58..30c9fa6c2d83d958b1d0f009fd7c0989df6bf73b 100644
--- a/Post/PViewDataList.h
+++ b/Post/PViewDataList.h
@@ -137,6 +137,7 @@ class PViewDataList : public PViewData {
                         bool forceNodeData=false, bool forceElementData=false);
   virtual void importLists(int N[24], std::vector<double> *V[24]);
   virtual void getListPointers(int N[24], std::vector<double> *V[24]);
+  void importList(int index, int n, const std::vector<double> &v, bool finalize);
 };
 
 #endif
diff --git a/Post/PViewDataListIO.cpp b/Post/PViewDataListIO.cpp
index d6ef15e8113df02ce42cc59ca0e178758d450357..ddbb768ae650e003ce10a72415f261e570bf442e 100644
--- a/Post/PViewDataListIO.cpp
+++ b/Post/PViewDataListIO.cpp
@@ -723,6 +723,21 @@ void PViewDataList::importLists(int N[24], std::vector<double> *V[24])
   finalize();
 }
 
+void PViewDataList::importList(int index, int n, const std::vector<double> &v,
+                               bool fin)
+{
+  if(index < 0 || index >= 24){
+    Msg::Error("Wrong list index to import");
+    return;
+  }
+  std::vector<double> *list = 0;
+  int *nbe = 0, nbc, nbn;
+  _getRawData(index, &list, &nbe, &nbc, &nbn);
+  *nbe = n;
+  *list = v; // deep copy
+  if(fin) finalize();
+}
+
 void PViewDataList::getListPointers(int N[24], std::vector<double> *V[24])
 {
   for(int i = 0; i < 24; i++){
diff --git a/Post/PViewIO.cpp b/Post/PViewIO.cpp
index d0742019bf14a2078e163e680d73ffa9b9f56daf..dd87e7d32c5fff9558bb4a3f7b66f99203d873c6 100644
--- a/Post/PViewIO.cpp
+++ b/Post/PViewIO.cpp
@@ -302,8 +302,10 @@ bool PView::write(const std::string &fileName, int format, bool append)
   case 3: ret = _data->writeSTL(fileName); break;
   case 4: ret = _data->writeTXT(fileName); break;
   case 5: ret = _data->writeMSH(fileName, CTX::instance()->mesh.mshFileVersion,
-                                CTX::instance()->mesh.binary, true, false,
-                                0, true, CTX::instance()->post.forceNodeData,
+                                CTX::instance()->mesh.binary,
+                                CTX::instance()->post.saveMesh, false, 0,
+                                CTX::instance()->post.saveInterpolationMatrices,
+                                CTX::instance()->post.forceNodeData,
                                 CTX::instance()->post.forceElementData); break;
   case 6: ret = _data->writeMED(fileName); break;
   case 7: ret = writeX3D(fileName); break;
@@ -316,8 +318,10 @@ bool PView::write(const std::string &fileName, int format, bool append)
         ret = _data->writeSTL(fileName);
       else if(ext == ".msh")
         ret = _data->writeMSH(fileName, CTX::instance()->mesh.mshFileVersion,
-                              CTX::instance()->mesh.binary, true, false,
-                              0, true, CTX::instance()->post.forceNodeData,
+                              CTX::instance()->mesh.binary,
+                              CTX::instance()->post.saveMesh, false, 0,
+                              CTX::instance()->post.saveInterpolationMatrices,
+                              CTX::instance()->post.forceNodeData,
                               CTX::instance()->post.forceElementData);
       else if(ext == ".med")
         ret = _data->writeMED(fileName);
diff --git a/contrib/HighOrderMeshOptimizer/OptHomRun.cpp b/contrib/HighOrderMeshOptimizer/OptHomRun.cpp
index 65f06783ef0d47789176c708a9ab5f4ff8e43e59..530eb181a96f88f2e1b914f48b2b55d16fb28174 100644
--- a/contrib/HighOrderMeshOptimizer/OptHomRun.cpp
+++ b/contrib/HighOrderMeshOptimizer/OptHomRun.cpp
@@ -606,7 +606,7 @@ double ComputeDistanceToGeometry (GEntity *ge , int distanceDefinition, double t
       const double DISTE =computeBndDist(el,distanceDefinition, tolerance);
       if (DISTE != 0.0){
         NUM++;
-        //        if(distanceDefinition == 1)printf("%d %12.5E\n",iEl,DISTE);
+        // if(distanceDefinition == 1)printf("%d %12.5E\n",iEl,DISTE);
         maxd = std::max(maxd,DISTE);
         sum += DISTE;
       }
@@ -671,7 +671,7 @@ void HighOrderMeshOptimizer(GModel *gm, OptHomParameters &p)
         if (jmin < p.BARRIER_MIN || jmax > p.BARRIER_MAX) badasses.insert(el);
       }
     }
-    printf("maxdist = %g badasses size = %lu\n", maxdist, badasses.size());
+    Msg::Info("maxdist = %g badasses size = %lu", maxdist, badasses.size());
     if (p.strategy == 0)
       optimizeConnectedBlobs(vertex2elements, element2entity, badasses, p, samples, false);
     else if (p.strategy == 2)
diff --git a/contrib/mobile/drawMesh.cpp b/contrib/mobile/drawMesh.cpp
index eb27954f986a32ef56106c8dc6c4aa7581ecb8cb..e13d6c4a8880cd69b8969f4141006dded6929d5d 100644
--- a/contrib/mobile/drawMesh.cpp
+++ b/contrib/mobile/drawMesh.cpp
@@ -8,8 +8,6 @@
 
 #include <gmsh/GmshGlobal.h>
 #include <gmsh/GModel.h>
-#include <gmsh/GEdgeCompound.h>
-#include <gmsh/GFaceCompound.h>
 #include <gmsh/PView.h>
 #include <gmsh/PViewData.h>
 #include <gmsh/Context.h>
@@ -57,33 +55,20 @@ void drawMeshVertex(GVertex *e)
 
 void drawMeshEdge(GEdge *e)
 {
-  if(!e->getVisibility()) {
-    if(e->getCompound()) {
-      if(!e->getCompound()->getVisibility()) return;
-    }
-    else
-      return;
-  }
+  if(!e->getVisibility()) return;
   glLineWidth(CTX::instance()->mesh.lineWidth);
   drawArray(e->va_lines, GL_LINES, true);
 }
 
 void drawMeshFace(GFace *f)
 {
-  if(!f->getVisibility()) {
-    if(f->getCompound()) {
-      if(!f->getCompound()->getVisibility()) return;
-    }
-    else
-      return;
-  }
+  if(!f->getVisibility()) return;
   drawArray(f->va_lines, GL_LINES, true);
 }
 
 void drawMeshRegion(GRegion *r)
 {
   if(!r->getVisibility()) return;
-
   drawArray(r->va_lines, GL_LINES, true);
 }
 
diff --git a/contrib/mobile/utils/ios_build.sh b/contrib/mobile/utils/ios_build.sh
index 5f6c6065271db48c44f4443245b6025e6fb9fca3..078c4a4a207d53534ad6fed6da7fb2efc74c7a43 100755
--- a/contrib/mobile/utils/ios_build.sh
+++ b/contrib/mobile/utils/ios_build.sh
@@ -54,9 +54,9 @@ getdp_framework="$frameworks_dir/getdp.framework"
 occt_framework="$frameworks_dir/occt.framework"
 
 if [ $enable_simulator != 0 ]; then
-  cmake_default="-DDEFAULT=0 -DCMAKE_TOOLCHAIN_FILE=$gmsh_git/contrib/mobile/utils/iOS.cmake -DIOS_PLATFORM=SIMULATOR -DENABLE_BUILD_IOS=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES=x86_64 -GXcode"
+  cmake_default="-DDEFAULT=0 -DENABLE_INTERNAL_DEVELOPER_API=1 -DCMAKE_TOOLCHAIN_FILE=$gmsh_git/contrib/mobile/utils/iOS.cmake -DIOS_PLATFORM=SIMULATOR -DENABLE_BUILD_IOS=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES=x86_64 -GXcode"
 else
-  cmake_default="-DDEFAULT=0 -DCMAKE_TOOLCHAIN_FILE=$gmsh_git/contrib/mobile/utils/iOS.cmake -DIOS_PLATFORM=OS -DENABLE_BUILD_IOS=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES=armv7;armv7s;arm64 -GXcode"
+  cmake_default="-DDEFAULT=0 -DENABLE_INTERNAL_DEVELOPER_API=1 -DCMAKE_TOOLCHAIN_FILE=$gmsh_git/contrib/mobile/utils/iOS.cmake -DIOS_PLATFORM=OS -DENABLE_BUILD_IOS=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES=armv7;armv7s;arm64 -GXcode"
 fi
 
 build_cmd="xcodebuild -target lib -configuration Release"
diff --git a/demos/api/README.txt b/demos/api/README.txt
index 99119011865646acaaa916b6c0839648d606fa5f..63b050491db69c028ba7ff7747b16c0cdb5b5307 100644
--- a/demos/api/README.txt
+++ b/demos/api/README.txt
@@ -1,2 +1,29 @@
-This directory contains examples on how to use the Gmsh API in C++ and in Python.
+This directory contains examples on how to use the Gmsh API in C++ and in
+Python. The full API is available in Common/gmsh.h.
 
+The files t1.{cpp,py}, t2.{cpp,py}, ... are reimplementations in C++ and Python
+of the corresponding tutorials in gmsh/tutorials.
+
+1) Build and install Gmsh, the dynamic Gmsh library and the Python wrappers:
+
+  cd gmsh
+  mkdir build
+  cd build
+  cmake -DENABLE_WRAP_PYTHON=1 ..
+  make
+  make install
+  cd ..
+
+2a) To build the C++ examples:
+
+  cd demos/api
+  mkdir build
+  cd build
+  cmake ..
+  make
+  ./t1
+
+2b) To run the Python examples:
+
+  export PYTHON_PATH=/path/to/gmsh/build
+  python demos/api/t1.py
diff --git a/demos/api/boolean.cpp b/demos/api/boolean.cpp
index 22eb6800eb76f1bdcb406e579f8f9e1158457e2b..4dd2ee309cf507aa68f21dde2c4327101946353c 100644
--- a/demos/api/boolean.cpp
+++ b/demos/api/boolean.cpp
@@ -4,36 +4,36 @@
 
 int main(int argc, char **argv)
 {
-  gmshInitialize(argc, argv);
-  gmshOptionSetNumber("General.Terminal", 1);
+  gmsh::initialize(argc, argv);
+  gmsh::option::setNumber("General.Terminal", 1);
 
-  gmshModelCreate("boolean");
+  gmsh::model::add("boolean");
 
   // from http://en.wikipedia.org/wiki/Constructive_solid_geometry
 
-  gmshOptionSetNumber("Mesh.Algorithm", 6);
-  gmshOptionSetNumber("Mesh.CharacteristicLengthMin", 0.4);
-  gmshOptionSetNumber("Mesh.CharacteristicLengthMax", 0.4);
+  gmsh::option::setNumber("Mesh.Algorithm", 6);
+  gmsh::option::setNumber("Mesh.CharacteristicLengthMin", 0.4);
+  gmsh::option::setNumber("Mesh.CharacteristicLengthMax", 0.4);
 
   double R = 1.4, Rs = R*.7, Rt = R*1.25;
 
   std::vector<std::pair<int, int> > ov;
   std::vector<std::vector<std::pair<int, int> > > ovv;
-  gmshModelOccAddBox(-R,-R,-R, 2*R,2*R,2*R, 1);
-  gmshModelOccAddSphere(0,0,0,Rt, 2);
-  gmshModelOccBooleanIntersection({{3, 1}}, {{3, 2}}, ov, ovv, 3);
-  gmshModelOccAddCylinder(-2*R,0,0, 4*R,0,0, Rs, 4);
-  gmshModelOccAddCylinder(0,-2*R,0, 0,4*R,0, Rs, 5);
-  gmshModelOccAddCylinder(0,0,-2*R, 0,0,4*R, Rs, 6);
-  gmshModelOccBooleanUnion({{3, 4}, {3, 5}}, {{3, 6}}, ov, ovv, 7);
-  gmshModelOccBooleanDifference({{3, 3}}, {{3, 7}}, ov, ovv, 8);
+  gmsh::model::occ::addBox(-R,-R,-R, 2*R,2*R,2*R, 1);
+  gmsh::model::occ::addSphere(0,0,0,Rt, 2);
+  gmsh::model::occ::booleanIntersection({{3, 1}}, {{3, 2}}, ov, ovv, 3);
+  gmsh::model::occ::addCylinder(-2*R,0,0, 4*R,0,0, Rs, 4);
+  gmsh::model::occ::addCylinder(0,-2*R,0, 0,4*R,0, Rs, 5);
+  gmsh::model::occ::addCylinder(0,0,-2*R, 0,0,4*R, Rs, 6);
+  gmsh::model::occ::booleanUnion({{3, 4}, {3, 5}}, {{3, 6}}, ov, ovv, 7);
+  gmsh::model::occ::booleanDifference({{3, 3}}, {{3, 7}}, ov, ovv, 8);
 
-  gmshModelOccSynchronize();
+  gmsh::model::occ::synchronize();
 
-  gmshModelMesh(3);
+  gmsh::model::mesh::generate(3);
 
-  gmshExport("boolean.msh");
+  gmsh::write("boolean.msh");
 
-  gmshFinalize();
+  gmsh::finalize();
   return 0;
 }
diff --git a/demos/api/boolean.py b/demos/api/boolean.py
index 9bbfbf1a1a3b257e636bb5d8dee8a4fad9a51bb1..975deb1963a51089b2f6230b2fc4054333851e93 100644
--- a/demos/api/boolean.py
+++ b/demos/api/boolean.py
@@ -1,38 +1,38 @@
 # This reimplements gmsh/demos/boolean/boolean.geo in Python.
 
-from gmsh import *
+import gmsh
 import sys
 
-gmshInitialize(sys.argv)
+gmsh.initialize(sys.argv)
 
-gmshOptionSetNumber("General.Terminal", 1)
+gmsh.optionSetNumber("General.Terminal", 1)
 
-gmshModelCreate("boolean")
+gmsh.modelAdd("boolean")
 
 # from http://en.wikipedia.org/wiki/Constructive_solid_geometry
 
-gmshOptionSetNumber("Mesh.Algorithm", 6);
-gmshOptionSetNumber("Mesh.CharacteristicLengthMin", 0.4);
-gmshOptionSetNumber("Mesh.CharacteristicLengthMax", 0.4);
+gmsh.optionSetNumber("Mesh.Algorithm", 6);
+gmsh.optionSetNumber("Mesh.CharacteristicLengthMin", 0.4);
+gmsh.optionSetNumber("Mesh.CharacteristicLengthMax", 0.4);
 
 R = 1.4; Rs = R*.7; Rt = R*1.25
 
-ov = PairVector(); ovv = PairVectorVector()
+ov = gmsh.PairVector(); ovv = gmsh.PairVectorVector()
 
-gmshModelOccAddBox(-R,-R,-R, 2*R,2*R,2*R, 1)
-gmshModelOccAddSphere(0,0,0,Rt, 2)
-gmshModelOccBooleanIntersection([(3, 1)], [(3, 2)], ov, ovv, 3)
-gmshModelOccAddCylinder(-2*R,0,0, 4*R,0,0, Rs, 4)
-gmshModelOccAddCylinder(0,-2*R,0, 0,4*R,0, Rs, 5)
-gmshModelOccAddCylinder(0,0,-2*R, 0,0,4*R, Rs, 6)
-gmshModelOccBooleanUnion([(3, 4), (3, 5)], [(3, 6)], ov, ovv, 7)
-gmshModelOccBooleanDifference([(3, 3)], [(3, 7)], ov, ovv, 8)
+gmsh.modelOccAddBox(-R,-R,-R, 2*R,2*R,2*R, 1)
+gmsh.modelOccAddSphere(0,0,0,Rt, 2)
+gmsh.modelOccBooleanIntersection([(3, 1)], [(3, 2)], ov, ovv, 3)
+gmsh.modelOccAddCylinder(-2*R,0,0, 4*R,0,0, Rs, 4)
+gmsh.modelOccAddCylinder(0,-2*R,0, 0,4*R,0, Rs, 5)
+gmsh.modelOccAddCylinder(0,0,-2*R, 0,0,4*R, Rs, 6)
+gmsh.modelOccBooleanUnion([(3, 4), (3, 5)], [(3, 6)], ov, ovv, 7)
+gmsh.modelOccBooleanDifference([(3, 3)], [(3, 7)], ov, ovv, 8)
 
-gmshModelOccSynchronize();
+gmsh.modelOccSynchronize();
 
-gmshModelMesh(3)
+gmsh.modelMeshGenerate(3)
 
-gmshExport("boolean.msh")
+gmsh.write("boolean.msh")
 
-gmshFinalize()
+gmsh.finalize()
 
diff --git a/demos/api/discrete.cpp b/demos/api/discrete.cpp
index 25753dde17508bbbe60dc5107d2b1faa82b054dd..ffe12cf559b6990d67fa662b0728f340b696a050 100644
--- a/demos/api/discrete.cpp
+++ b/demos/api/discrete.cpp
@@ -2,32 +2,32 @@
 
 int main(int argc, char **argv)
 {
-  gmshInitialize(argc, argv);
-  gmshOptionSetNumber("General.Terminal", 1);
+  gmsh::initialize(argc, argv);
+  gmsh::option::setNumber("General.Terminal", 1);
 
-  gmshModelCreate("test");
+  gmsh::model::add("test");
 
   // add discrete surface with tag 1
-  gmshModelAddDiscreteEntity(2, 1);
+  gmsh::model::addDiscreteEntity(2, 1);
 
   // add 4 mesh vertices
-  gmshModelSetMeshVertices(2, 1,
-                           {1, 2, 3, 4}, // vertex tags: 1, 2, 3, and 4
-                           {0., 0., 0., // coordinates of vertex 1
-                            1., 0., 0., // coordinates of vertex 2
-                            1., 1., 0., // ...
-                            0., 1., 0.});
+  gmsh::model::mesh::setVertices(2, 1,
+                                 {1, 2, 3, 4}, // vertex tags: 1, 2, 3, and 4
+                                 {0., 0., 0., // coordinates of vertex 1
+                                  1., 0., 0., // coordinates of vertex 2
+                                  1., 1., 0., // ...
+                                  0., 1., 0.});
 
   // add 2 triangles
-  gmshModelSetMeshElements(2, 1,
-                           {2}, // single type : 3-node triangle
-                           {{1, 2}}, // triangle tags: 1 and 2
-                           {{1, 2, 3, // triangle 1: vertices 1, 2, 3
-                             1, 3, 4}}); // triangle 2: vertices 1, 3, 4
+  gmsh::model::mesh::setElements(2, 1,
+                                 {2}, // single type : 3-node triangle
+                                 {{1, 2}}, // triangle tags: 1 and 2
+                                 {{1, 2, 3, // triangle 1: vertices 1, 2, 3
+                                   1, 3, 4}}); // triangle 2: vertices 1, 3, 4
 
   // export the mesh ; use explore.cpp to read and examine the mesh
-  gmshExport("test.msh");
+  gmsh::write("test.msh");
 
-  gmshFinalize();
+  gmsh::finalize();
   return 0;
 }
diff --git a/demos/api/discrete.py b/demos/api/discrete.py
index 2bb70a03dd267a509c9560063a94a569da886fc4..84003f726fefbe427c050a4e87805af786af8dfa 100644
--- a/demos/api/discrete.py
+++ b/demos/api/discrete.py
@@ -1,18 +1,18 @@
 #!/usr/bin/env python
 
-from gmsh import *
+import gmsh
 import sys
 
-gmshInitialize(sys.argv)
-gmshOptionSetNumber("General.Terminal", 1)
+gmsh.initialize(sys.argv)
+gmsh.optionSetNumber("General.Terminal", 1)
 
-gmshModelCreate("test");
+gmsh.modelAdd("test");
 
 # add discrete surface with tag 1
-gmshModelAddDiscreteEntity(2, 1)
+gmsh.modelAddDiscreteEntity(2, 1)
 
 # add 4 mesh vertices
-gmshModelSetMeshVertices(2, 1,
+gmsh.modelMeshSetVertices(2, 1,
                          [1, 2, 3, 4], # vertex tags: 1, 2, 3, and 4
                          [0., 0., 0., # coordinates of vertex 1
                           1., 0., 0., # coordinates of vertex 2
@@ -20,14 +20,14 @@ gmshModelSetMeshVertices(2, 1,
                           0., 1., 0.])
 
 # add 2 triangles
-gmshModelSetMeshElements(2, 1,
+gmsh.modelMeshSetElements(2, 1,
                          [2], # single type : 3-node triangle
                          [[1, 2]], # triangle tags: 1 and 2
                          [[1, 2, 3, # triangle 1: vertices 1, 2, 3
-                           1, 3, 4]]); # triangle 2: vertices 1, 3, 4
+                           1, 3, 4]]) # triangle 2: vertices 1, 3, 4
 
 # export the mesh ; use explore.py to read and examine the mesh
-gmshExport("test.msh")
+gmsh.write("test.msh")
 
-gmshFinalize()
+gmsh.finalize()
 
diff --git a/demos/api/explore.cpp b/demos/api/explore.cpp
index 6933ec3bfa5318da3918501379afec3fe4cb4a6a..6336a43dc2f50df3947cf109445549c1a5113f23 100644
--- a/demos/api/explore.cpp
+++ b/demos/api/explore.cpp
@@ -8,26 +8,25 @@ int main(int argc, char **argv)
     return 1;
   }
 
-  gmshInitialize();
-  gmshOptionSetNumber("General.Terminal", 1);
-  gmshOpen(argv[1]);
+  gmsh::initialize();
+  gmsh::option::setNumber("General.Terminal", 1);
+  gmsh::open(argv[1]);
 
   // get all elementary entities in the model
   std::vector<std::pair<int, int> > entities;
-  gmshModelGetEntities(entities);
+  gmsh::model::getEntities(entities);
 
   for(unsigned int i = 0; i < entities.size(); i++){
-
     // get the mesh vertices for each elementary entity
     std::vector<int> vertexTags;
     std::vector<double> vertexCoords, vertexParams;
     int dim = entities[i].first, tag = entities[i].second;
-    gmshModelGetMeshVertices(dim, tag, vertexTags, vertexCoords, vertexParams);
+    gmsh::model::mesh::getVertices(dim, tag, vertexTags, vertexCoords, vertexParams);
 
     // get the mesh elements for each elementary entity
     std::vector<int> elemTypes;
     std::vector<std::vector<int> > elemTags, elemVertexTags;
-    gmshModelGetMeshElements(dim, tag, elemTypes, elemTags, elemVertexTags);
+    gmsh::model::mesh::getElements(dim, tag, elemTypes, elemTags, elemVertexTags);
 
     // report some statistics
     int numElem = 0;
@@ -38,6 +37,6 @@ int main(int argc, char **argv)
               << dim << "," << tag << ")\n";
   }
 
-  gmshFinalize();
+  gmsh::finalize();
   return 0;
 }
diff --git a/demos/api/explore.py b/demos/api/explore.py
index 77059ac4a2ca26deb23983d3f8f731a50221738f..a4656cfcc255107330f6002aefca33622a469fbb 100644
--- a/demos/api/explore.py
+++ b/demos/api/explore.py
@@ -1,32 +1,32 @@
 #!/usr/bin/env python
 
-from gmsh import *
+import gmsh
 import sys
 
 if len(sys.argv) < 2:
     print "Usage: " + sys.argv[0] + " file.msh [options]"
     exit(0)
 
-gmshInitialize()
-gmshOptionSetNumber("General.Terminal", 1)
-gmshOpen(sys.argv[1])
+gmsh.initialize()
+gmsh.optionSetNumber("General.Terminal", 1)
+gmsh.open(sys.argv[1])
 
 # get all elementary entities in the model
-entities = PairVector()
-gmshModelGetEntities(entities)
+entities = gmsh.PairVector()
+gmsh.modelGetEntities(entities)
 
 for e in entities:
     # get the mesh vertices for each elementary entity
-    vertexTags = IntVector()
-    vertexCoords = DoubleVector(); vertexParams = DoubleVector()
-    gmshModelGetMeshVertices(e[0], e[1], vertexTags, vertexCoords, vertexParams)
+    vertexTags = gmsh.IntVector()
+    vertexCoords = gmsh.DoubleVector(); vertexParams = gmsh.DoubleVector()
+    gmsh.modelMeshGetVertices(e[0], e[1], vertexTags, vertexCoords, vertexParams)
     # get the mesh elements for each elementary entity
-    elemTypes = IntVector()
-    elemTags = IntVectorVector(); elemVertexTags = IntVectorVector()
-    gmshModelGetMeshElements(e[0], e[1], elemTypes, elemTags, elemVertexTags)
+    elemTypes = gmsh.IntVector()
+    elemTags = gmsh.IntVectorVector(); elemVertexTags = gmsh.IntVectorVector()
+    gmsh.modelMeshGetElements(e[0], e[1], elemTypes, elemTags, elemVertexTags)
     # report some statistics
     numElem = sum(len(i) for i in elemTags)
     print str(vertexTags.size()) + " mesh vertices " + str(numElem),\
           "mesh elements on entity " + str(e)
 
-gmshFinalize()
+gmsh.finalize()
diff --git a/demos/api/open.cpp b/demos/api/open.cpp
index a25096fa248fa7d3f99ac12443b7473eeefe2612..0f0042995f2113316ea4018f76d2a7e361157cf1 100644
--- a/demos/api/open.cpp
+++ b/demos/api/open.cpp
@@ -8,12 +8,12 @@ int main(int argc, char **argv)
     return 1;
   }
 
-  gmshInitialize();
-  gmshOptionSetNumber("General.Terminal", 1);
-  gmshOpen(argv[1]);
-  gmshModelMesh(3);
-  gmshExport("test.msh");
-  gmshFinalize();
+  gmsh::initialize();
+  gmsh::option::setNumber("General.Terminal", 1);
+  gmsh::open(argv[1]);
+  gmsh::model::mesh::generate(3);
+  gmsh::write("test.msh");
+  gmsh::finalize();
 
   return 0;
 }
diff --git a/demos/api/open.py b/demos/api/open.py
index 4f09a068f2c47915a3805fc20f7b594f64880627..d3df5f7263d94b9e8b58e5636da9b603b6ce5d96 100644
--- a/demos/api/open.py
+++ b/demos/api/open.py
@@ -1,16 +1,16 @@
 #!/usr/bin/env python
 
-from gmsh import *
+import gmsh
 import sys
 
 if len(sys.argv) < 2:
     print "Usage: " + sys.argv[0] + " file.geo [options]"
     exit(0)
 
-gmshInitialize()
-gmshOptionSetNumber("General.Terminal", 1)
-gmshOpen(sys.argv[1])
-gmshModelMesh(3)
-gmshExport("test.msh")
-gmshFinalize()
+gmsh.initialize()
+gmsh.optionSetNumber("General.Terminal", 1)
+gmsh.open(sys.argv[1])
+gmsh.modelMeshGenerate(3)
+gmsh.write("test.msh")
+gmsh.finalize()
 
diff --git a/demos/api/plugin.cpp b/demos/api/plugin.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..016e2615f7bc962ddfe28be5a4f21e6a7ac90ce6
--- /dev/null
+++ b/demos/api/plugin.cpp
@@ -0,0 +1,43 @@
+#include <gmsh.h>
+
+int main(int argc, char **argv)
+{
+  gmsh::initialize();
+  gmsh::option::setNumber("General.Terminal", 1);
+
+  // Copied from discrete.cpp...
+  gmsh::model::add("test");
+  gmsh::model::addDiscreteEntity(2, 1);
+  gmsh::model::mesh::setVertices(2, 1, {1, 2, 3, 4},
+                                 {0., 0., 0.,
+                                  1., 0., 0.,
+                                  1., 1., 0.,
+                                  0., 1., 0.});
+  gmsh::model::mesh::setElements(2, 1, {2}, {{1, 2}},
+                                 {{1, 2, 3,
+                                   1, 3, 4}});
+  // ... end of copy
+
+  // create a view with some data
+  int t = gmsh::view::add("some data");
+  gmsh::view::addModelData(t, "test", "NodeData",
+                           {1, 2, 3, 4},
+                           {{1.},{10.},{20.},{1.}});
+
+  // compute the iso-curve at value 11
+  gmsh::plugin::setNumber("Isosurface", "Value", 11.);
+  gmsh::plugin::run("Isosurface");
+
+  // delete the source view
+  gmsh::view::remove(t);
+
+  // check how many views the plugin created (a priori, a single one)
+  std::vector<int> tags;
+  gmsh::view::getTags(tags);
+  if(tags.size() == 1)
+    gmsh::view::write(tags[0], "iso.msh");
+
+  gmsh::finalize();
+  return 0;
+}
+
diff --git a/demos/api/plugin.py b/demos/api/plugin.py
new file mode 100644
index 0000000000000000000000000000000000000000..f96c425aa6fc92b7df23fc006f7baf525e0a271b
--- /dev/null
+++ b/demos/api/plugin.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+
+import gmsh
+import sys
+
+gmsh.initialize(sys.argv)
+gmsh.optionSetNumber("General.Terminal", 1)
+
+# Copied from discrete.py...
+gmsh.modelAdd("test");
+gmsh.modelAddDiscreteEntity(2, 1)
+gmsh.modelMeshSetVertices(2, 1, [1, 2, 3, 4],
+                         [0., 0., 0.,
+                          1., 0., 0.,
+                          1., 1., 0.,
+                          0., 1., 0.])
+gmsh.modelMeshSetElements(2, 1, [2], [[1, 2]],
+                         [[1, 2, 3,
+                           1, 3, 4]])
+# ... end of copy
+
+# create a view with some data
+t = gmsh.viewAdd("some data")
+gmsh.viewAddModelData(t, "test", "NodeData",
+                     [1, 2, 3, 4],
+                     [[1.],[10.],[20.],[1.]])
+
+# compute the iso-curve at value 11
+gmsh.pluginSetNumber("Isosurface", "Value", 11.)
+gmsh.pluginRun("Isosurface")
+
+# delete the source view
+gmsh.viewRemove(t)
+
+# check how many views the plugin created (a priori, a single one)
+tags = gmsh.IntVector()
+gmsh.viewGetTags(tags)
+if tags.size() == 1:
+    gmsh.viewWrite(tags[0], "iso.msh")
+
+gmsh.finalize()
+
+
diff --git a/demos/api/t1.cpp b/demos/api/t1.cpp
index dbecc7040a554a4912150798b7e70894451ff975..049ce3f8965b02a88e0c4f16a883e35371deb51d 100644
--- a/demos/api/t1.cpp
+++ b/demos/api/t1.cpp
@@ -10,17 +10,17 @@
 int main(int argc, char **argv)
 {
   // Before using any functions in the C++ API, Gmsh must be initialized.
-  gmshInitialize();
+  gmsh::initialize();
 
   // By default Gmsh will not print out any messages: in order to output
   // messages on the terminal, just set the standard Gmsh option
   // "General.Terminal" (same format and meaning as in .geo files) using
   // gmshOptionSetNumber():
-  gmshOptionSetNumber("General.Terminal", 1);
+  gmsh::option::setNumber("General.Terminal", 1);
 
-  // This creates a new model, named "t1". If gmshModelCreate() is not called, a
+  // This adds a new model, named "t1". If gmsh::model::add() is not called, a
   // new default (unnamed) model will be created on the fly, if necessary.
-  gmshModelCreate("t1");
+  gmsh::model::add("t1");
 
   // The C++ API provides direct access to the internal CAD kernels. The
   // built-in CAD kernel was used in t1.geo: the corresponding API functions
@@ -33,35 +33,35 @@ int main(int argc, char **argv)
   //
   // - the last (optional) argument is the point tag
   double lc = 1e-2;
-  gmshModelGeoAddPoint(0, 0, 0, lc, 1);
-  gmshModelGeoAddPoint(.1, 0,  0, lc, 2);
-  gmshModelGeoAddPoint(.1, .3, 0, lc, 3);
-  gmshModelGeoAddPoint(0,  .3, 0, lc, 4);
+  gmsh::model::geo::addPoint(0, 0, 0, lc, 1);
+  gmsh::model::geo::addPoint(.1, 0,  0, lc, 2);
+  gmsh::model::geo::addPoint(.1, .3, 0, lc, 3);
+  gmsh::model::geo::addPoint(0,  .3, 0, lc, 4);
 
   // The API to create lines with the built-in kernel follows the same
   // conventions: the first 2 arguments are point tags, the last (optional one)
   // is the line tag.
-  gmshModelGeoAddLine(1, 2, 1);
-  gmshModelGeoAddLine(3, 2, 2);
-  gmshModelGeoAddLine(3, 4, 3);
-  gmshModelGeoAddLine(4, 1, 4);
+  gmsh::model::geo::addLine(1, 2, 1);
+  gmsh::model::geo::addLine(3, 2, 2);
+  gmsh::model::geo::addLine(3, 4, 3);
+  gmsh::model::geo::addLine(4, 1, 4);
 
   // The philosophy to construct line loops and surfaces is similar: the first
   // argument is now a vector of integers.
-  gmshModelGeoAddLineLoop({4, 1, -2, 3}, 1);
-  gmshModelGeoAddPlaneSurface({1}, 1);
+  gmsh::model::geo::addLineLoop({4, 1, -2, 3}, 1);
+  gmsh::model::geo::addPlaneSurface({1}, 1);
 
   // Physical groups are defined by providing the dimension of the group (0 for
   // physical points, 1 for physical lines, 2 for physical surfaces and 3 for
   // phsyical volumes) followed by a vector of entity tags. The last (optional)
   // argument is the tag of the new group to create.
-  gmshModelAddPhysicalGroup(0, {1, 2}, 1);
-  gmshModelAddPhysicalGroup(1, {1, 2}, 2);
-  gmshModelAddPhysicalGroup(2, {1}, 6);
+  gmsh::model::addPhysicalGroup(0, {1, 2}, 1);
+  gmsh::model::addPhysicalGroup(1, {1, 2}, 2);
+  gmsh::model::addPhysicalGroup(2, {1}, 6);
 
   // Physical names are also defined by providing the dimension and tag of the
   // entity.
-  gmshModelSetPhysicalName(2, 6, "My surface");
+  gmsh::model::setPhysicalName(2, 6, "My surface");
 
   // Before it can be meshed, the internal CAD representation must be
   // synchronized with the Gmsh model, which will create the relevant Gmsh data
@@ -70,15 +70,15 @@ int main(int argc, char **argv)
   // they involve a non trivial amount of processing; so while you could
   // synchronize the internal CAD data after every CAD command, it is usually
   // better to minimize the number of synchronization points.
-  gmshModelGeoSynchronize();
+  gmsh::model::geo::synchronize();
 
   // We can then generate a 2D mesh...
-  gmshModelMesh(2);
+  gmsh::model::mesh::generate(2);
 
   // ... and save it to disk
-  gmshExport("t1.msh");
+  gmsh::write("t1.msh");
 
   // This should be called at the end:
-  gmshFinalize();
+  gmsh::finalize();
   return 0;
 }
diff --git a/demos/api/t1.py b/demos/api/t1.py
index 83d4fc447232ffcc1b949c52aeda7fdea900e53b..869810a6aa20110c875619a32c9ce279a476e895 100644
--- a/demos/api/t1.py
+++ b/demos/api/t1.py
@@ -7,19 +7,19 @@
 # of the Python API.
 
 # The API is entirely defined in the gmsh module
-from gmsh import *
+import gmsh
 
 # Before using any functions in the Python API, Gmsh must be initialized.
-gmshInitialize()
+gmsh.initialize()
 
 # By default Gmsh will not print out any messages: in order to output messages
 # on the terminal, just set the standard Gmsh option "General.Terminal" (same
 # format and meaning as in .geo files) using gmshOptionSetNumber():
-gmshOptionSetNumber("General.Terminal", 1)
+gmsh.optionSetNumber("General.Terminal", 1)
 
 # This creates a new model, named "t1". If gmshModelCreate() is not called, a
 # new default (unnamed) model will be created on the fly, if necessary.
-gmshModelCreate("t1")
+gmsh.modelAdd("t1")
 
 # The Python API provides direct access to the internal CAD kernels. The
 # built-in CAD kernel was used in t1.geo: the corresponding API functions have
@@ -32,35 +32,35 @@ gmshModelCreate("t1")
 #
 # - the last (optional) argument is the point tag
 lc = 1e-2
-gmshModelGeoAddPoint(0, 0, 0, lc, 1)
-gmshModelGeoAddPoint(.1, 0,  0, lc, 2)
-gmshModelGeoAddPoint(.1, .3, 0, lc, 3)
-gmshModelGeoAddPoint(0, .3, 0, lc, 4)
+gmsh.modelGeoAddPoint(0, 0, 0, lc, 1)
+gmsh.modelGeoAddPoint(.1, 0,  0, lc, 2)
+gmsh.modelGeoAddPoint(.1, .3, 0, lc, 3)
+gmsh.modelGeoAddPoint(0, .3, 0, lc, 4)
 
 # The API to create lines with the built-in kernel follows the same
 # conventions: the first 2 arguments are point tags, the last (optional one)
 # is the line tag.
-gmshModelGeoAddLine(1, 2, 1)
-gmshModelGeoAddLine(3, 2, 2)
-gmshModelGeoAddLine(3, 4, 3)
-gmshModelGeoAddLine(4, 1, 4)
+gmsh.modelGeoAddLine(1, 2, 1)
+gmsh.modelGeoAddLine(3, 2, 2)
+gmsh.modelGeoAddLine(3, 4, 3)
+gmsh.modelGeoAddLine(4, 1, 4)
 
 # The philosophy to construct line loops and surfaces is similar: the first
 # argument is now a vector of integers.
-gmshModelGeoAddLineLoop([4, 1, -2, 3], 1)
-gmshModelGeoAddPlaneSurface([1], 1)
+gmsh.modelGeoAddLineLoop([4, 1, -2, 3], 1)
+gmsh.modelGeoAddPlaneSurface([1], 1)
 
 # Physical groups are defined by providing the dimension of the group (0 for
 # physical points, 1 for physical lines, 2 for physical surfaces and 3 for
 # phsyical volumes) followed by a vector of entity tags. The last (optional)
 # argument is the tag of the new group to create.
-gmshModelAddPhysicalGroup(0, [1, 2], 1)
-gmshModelAddPhysicalGroup(1, [1, 2], 2)
-gmshModelAddPhysicalGroup(2, [1], 6)
+gmsh.modelAddPhysicalGroup(0, [1, 2], 1)
+gmsh.modelAddPhysicalGroup(1, [1, 2], 2)
+gmsh.modelAddPhysicalGroup(2, [1], 6)
 
 # Physical names are also defined by providing the dimension and tag of the
 # entity.
-gmshModelSetPhysicalName(2, 6, "My surface")
+gmsh.modelSetPhysicalName(2, 6, "My surface")
 
 # Before it can be meshed, the internal CAD representation must be synchronized
 # with the Gmsh model, which will create the relevant Gmsh data structures. This
@@ -69,13 +69,13 @@ gmshModelSetPhysicalName(2, 6, "My surface")
 # trivial amount of processing; so while you could synchronize the internal CAD
 # data after every CAD command, it is usually better to minimize the number of
 # synchronization points.
-gmshModelGeoSynchronize()
+gmsh.modelGeoSynchronize()
 
 # We can then generate a 2D mesh...
-gmshModelMesh(2)
+gmsh.modelMeshGenerate(2)
 
 # ... and save it to disk
-gmshExport("t1.msh")
+gmsh.write("t1.msh")
 
 # This should be called at the end:
-gmshFinalize()
+gmsh.finalize()
diff --git a/demos/api/t10.cpp b/demos/api/t10.cpp
index 517a20225e4c4a41850354ac568019e453119ef1..c87fe66cb45d3ee1b1bed326328d25298f9b39dd 100644
--- a/demos/api/t10.cpp
+++ b/demos/api/t10.cpp
@@ -3,66 +3,69 @@
 #include <gmsh.h>
 #include <sstream>
 
+using namespace gmsh;
+
 int main(int argc, char **argv)
 {
-  gmshInitialize(argc, argv);
-  gmshOptionSetNumber("General.Terminal", 1);
+  initialize(argc, argv);
+  option::setNumber("General.Terminal", 1);
 
-  gmshModelCreate("t1");
+  model::add("t1");
 
   double lc = .15;
-  gmshModelGeoAddPoint(0.0,0.0,0,lc, 1);
-  gmshModelGeoAddPoint(1,0.0,0,lc, 2);
-  gmshModelGeoAddPoint(1,1,0,lc, 3);
-  gmshModelGeoAddPoint(0,1,0,lc, 4);
-  gmshModelGeoAddPoint(0.2,.5,0,lc, 5);
-
-  gmshModelGeoAddLine(1,2, 1);
-  gmshModelGeoAddLine(2,3, 2);
-  gmshModelGeoAddLine(3,4, 3);
-  gmshModelGeoAddLine(4,1, 4);
-
-  gmshModelGeoAddLineLoop({1,2,3,4}, 5);
-  gmshModelGeoAddPlaneSurface({5}, 6);
-
-  gmshModelFieldCreate("Attractor", 1);
-  gmshModelFieldSetNumbers(1, "NodesList", {5});
-  gmshModelFieldSetNumber(1, "NNodesByEdge", 100);
-  gmshModelFieldSetNumbers(1, "EdgesList", {2});
-
-  gmshModelFieldCreate("Threshold", 2);
-  gmshModelFieldSetNumber(2, "IField", 1);
-  gmshModelFieldSetNumber(2, "LcMin", lc / 30);
-  gmshModelFieldSetNumber(2, "LcMax", lc);
-  gmshModelFieldSetNumber(2, "DistMin", 0.15);
-  gmshModelFieldSetNumber(2, "DistMax", 0.5);
-
-  gmshModelFieldCreate("MathEval", 3);
-  gmshModelFieldSetString(3, "F", "Cos(4*3.14*x) * Sin(4*3.14*y) / 10 + 0.101");
-
-  gmshModelFieldCreate("Attractor", 4);
-  gmshModelFieldSetNumbers(4, "NodesList", {1});
-
-  gmshModelFieldCreate("MathEval", 5);
+  model::geo::addPoint(0.0,0.0,0,lc, 1);
+  model::geo::addPoint(1,0.0,0,lc, 2);
+  model::geo::addPoint(1,1,0,lc, 3);
+  model::geo::addPoint(0,1,0,lc, 4);
+  model::geo::addPoint(0.2,.5,0,lc, 5);
+
+  model::geo::addLine(1,2, 1);
+  model::geo::addLine(2,3, 2);
+  model::geo::addLine(3,4, 3);
+  model::geo::addLine(4,1, 4);
+
+  model::geo::addLineLoop({1,2,3,4}, 5);
+  model::geo::addPlaneSurface({5}, 6);
+
+  model::mesh::field::add("Attractor", 1);
+  model::mesh::field::setNumbers(1, "NodesList", {5});
+  model::mesh::field::setNumber(1, "NNodesByEdge", 100);
+  model::mesh::field::setNumbers(1, "EdgesList", {2});
+
+  model::mesh::field::add("Threshold", 2);
+  model::mesh::field::setNumber(2, "IField", 1);
+  model::mesh::field::setNumber(2, "LcMin", lc / 30);
+  model::mesh::field::setNumber(2, "LcMax", lc);
+  model::mesh::field::setNumber(2, "DistMin", 0.15);
+  model::mesh::field::setNumber(2, "DistMax", 0.5);
+
+  model::mesh::field::add("MathEval", 3);
+  model::mesh::field::setString(3, "F", "Cos(4*3.14*x) * Sin(4*3.14*y) / 10 + 0.101");
+
+  model::mesh::field::add("Attractor", 4);
+  model::mesh::field::setNumbers(4, "NodesList", {1});
+
+  model::mesh::field::add("MathEval", 5);
   std::stringstream stream;
   stream << "F4^3 + " << lc / 100;
-  gmshModelFieldSetString(5, "F", stream.str());
+  model::mesh::field::setString(5, "F", stream.str());
 
-  gmshModelFieldCreate("Box", 6);
-  gmshModelFieldSetNumber(6, "VIn", lc / 15);
-  gmshModelFieldSetNumber(6, "VOut", lc);
-  gmshModelFieldSetNumber(6, "XMin", 0.3);
-  gmshModelFieldSetNumber(6, "XMax", 0.6);
-  gmshModelFieldSetNumber(6, "YMin", 0.3);
-  gmshModelFieldSetNumber(6, "YMax", 0.6);
+  model::mesh::field::add("Box", 6);
+  model::mesh::field::setNumber(6, "VIn", lc / 15);
+  model::mesh::field::setNumber(6, "VOut", lc);
+  model::mesh::field::setNumber(6, "XMin", 0.3);
+  model::mesh::field::setNumber(6, "XMax", 0.6);
+  model::mesh::field::setNumber(6, "YMin", 0.3);
+  model::mesh::field::setNumber(6, "YMax", 0.6);
 
-  gmshModelFieldCreate("Min", 7);
-  gmshModelFieldSetNumbers(7, "FieldsList", {2, 3, 5, 6});
+  model::mesh::field::add("Min", 7);
+  model::mesh::field::setNumbers(7, "FieldsList", {2, 3, 5, 6});
 
-  gmshModelFieldSetAsBackground(7);
+  model::mesh::field::setAsBackground(7);
 
-  gmshModelGeoSynchronize();
-  gmshModelMesh(2);
-  gmshExport("t10.msh");
+  model::geo::synchronize();
+  model::mesh::generate(2);
+  write("t10.msh");
+  finalize();
   return 0;
 }
diff --git a/demos/api/t10.py b/demos/api/t10.py
index 5514bf0a8e8829e0989fc52be23280ad4b8b2c90..48142ab6403e4ef59fac001edcfe77b5221ab74e 100644
--- a/demos/api/t10.py
+++ b/demos/api/t10.py
@@ -2,63 +2,65 @@
 
 # This file reimplements gmsh/tutorial/t10.geo in Python.
 
-from gmsh import *
+import gmsh
 import math
 
-gmshInitialize()
-gmshOptionSetNumber("General.Terminal", 1)
+gmsh.initialize()
+gmsh.optionSetNumber("General.Terminal", 1)
 
-gmshModelCreate("t10")
+gmsh.modelAdd("t10")
 
 lc = .15
-gmshModelGeoAddPoint(0.0,0.0,0, lc, 1)
-gmshModelGeoAddPoint(1,0.0,0, lc, 2)
-gmshModelGeoAddPoint(1,1,0, lc, 3)
-gmshModelGeoAddPoint(0,1,0, lc, 4)
-gmshModelGeoAddPoint(0.2,.5,0, lc, 5)
-
-gmshModelGeoAddLine(1,2, 1);
-gmshModelGeoAddLine(2,3, 2);
-gmshModelGeoAddLine(3,4, 3);
-gmshModelGeoAddLine(4,1, 4);
-
-gmshModelGeoAddLineLoop([1,2,3,4], 5)
-gmshModelGeoAddPlaneSurface([5], 6)
-
-gmshModelFieldCreate("Attractor", 1)
-gmshModelFieldSetNumbers(1, "NodesList", [5])
-gmshModelFieldSetNumber(1, "NNodesByEdge", 100)
-gmshModelFieldSetNumbers(1, "EdgesList", [2])
-
-gmshModelFieldCreate("Threshold", 2);
-gmshModelFieldSetNumber(2, "IField", 1);
-gmshModelFieldSetNumber(2, "LcMin", lc / 30)
-gmshModelFieldSetNumber(2, "LcMax", lc)
-gmshModelFieldSetNumber(2, "DistMin", 0.15)
-gmshModelFieldSetNumber(2, "DistMax", 0.5)
-
-gmshModelFieldCreate("MathEval", 3)
-gmshModelFieldSetString(3, "F", "Cos(4*3.14*x) * Sin(4*3.14*y) / 10 + 0.101")
-
-gmshModelFieldCreate("Attractor", 4)
-gmshModelFieldSetNumbers(4, "NodesList", [1])
-
-gmshModelFieldCreate("MathEval", 5);
-gmshModelFieldSetString(5, "F", "F4^3 + " + str(lc / 100))
-
-gmshModelFieldCreate("Box", 6)
-gmshModelFieldSetNumber(6, "VIn", lc / 15)
-gmshModelFieldSetNumber(6, "VOut", lc)
-gmshModelFieldSetNumber(6, "XMin", 0.3)
-gmshModelFieldSetNumber(6, "XMax", 0.6)
-gmshModelFieldSetNumber(6, "YMin", 0.3)
-gmshModelFieldSetNumber(6, "YMax", 0.6)
-
-gmshModelFieldCreate("Min", 7)
-gmshModelFieldSetNumbers(7, "FieldsList", [2, 3, 5, 6])
-
-gmshModelFieldSetAsBackground(7)
-
-gmshModelGeoSynchronize()
-gmshModelMesh(2)
-gmshExport("t10.msh")
+gmsh.modelGeoAddPoint(0.0,0.0,0, lc, 1)
+gmsh.modelGeoAddPoint(1,0.0,0, lc, 2)
+gmsh.modelGeoAddPoint(1,1,0, lc, 3)
+gmsh.modelGeoAddPoint(0,1,0, lc, 4)
+gmsh.modelGeoAddPoint(0.2,.5,0, lc, 5)
+
+gmsh.modelGeoAddLine(1,2, 1);
+gmsh.modelGeoAddLine(2,3, 2);
+gmsh.modelGeoAddLine(3,4, 3);
+gmsh.modelGeoAddLine(4,1, 4);
+
+gmsh.modelGeoAddLineLoop([1,2,3,4], 5)
+gmsh.modelGeoAddPlaneSurface([5], 6)
+
+gmsh.modelMeshFieldAdd("Attractor", 1)
+gmsh.modelMeshFieldSetNumbers(1, "NodesList", [5])
+gmsh.modelMeshFieldSetNumber(1, "NNodesByEdge", 100)
+gmsh.modelMeshFieldSetNumbers(1, "EdgesList", [2])
+
+gmsh.modelMeshFieldAdd("Threshold", 2);
+gmsh.modelMeshFieldSetNumber(2, "IField", 1);
+gmsh.modelMeshFieldSetNumber(2, "LcMin", lc / 30)
+gmsh.modelMeshFieldSetNumber(2, "LcMax", lc)
+gmsh.modelMeshFieldSetNumber(2, "DistMin", 0.15)
+gmsh.modelMeshFieldSetNumber(2, "DistMax", 0.5)
+
+gmsh.modelMeshFieldAdd("MathEval", 3)
+gmsh.modelMeshFieldSetString(3, "F", "Cos(4*3.14*x) * Sin(4*3.14*y) / 10 + 0.101")
+
+gmsh.modelMeshFieldAdd("Attractor", 4)
+gmsh.modelMeshFieldSetNumbers(4, "NodesList", [1])
+
+gmsh.modelMeshFieldAdd("MathEval", 5);
+gmsh.modelMeshFieldSetString(5, "F", "F4^3 + " + str(lc / 100))
+
+gmsh.modelMeshFieldAdd("Box", 6)
+gmsh.modelMeshFieldSetNumber(6, "VIn", lc / 15)
+gmsh.modelMeshFieldSetNumber(6, "VOut", lc)
+gmsh.modelMeshFieldSetNumber(6, "XMin", 0.3)
+gmsh.modelMeshFieldSetNumber(6, "XMax", 0.6)
+gmsh.modelMeshFieldSetNumber(6, "YMin", 0.3)
+gmsh.modelMeshFieldSetNumber(6, "YMax", 0.6)
+
+gmsh.modelMeshFieldAdd("Min", 7)
+gmsh.modelMeshFieldSetNumbers(7, "FieldsList", [2, 3, 5, 6])
+
+gmsh.modelMeshFieldSetAsBackground(7)
+
+gmsh.modelGeoSynchronize()
+gmsh.modelMeshGenerate(2)
+gmsh.write("t10.msh")
+gmsh.finalize()
+
diff --git a/demos/api/t16.cpp b/demos/api/t16.cpp
index 055e0e3d23527be147159b379392dcd861f2d8d4..47c61e43cdda506f0163eadf1c01ef455df32766 100644
--- a/demos/api/t16.cpp
+++ b/demos/api/t16.cpp
@@ -4,47 +4,47 @@
 
 int main(int argc, char **argv)
 {
-  gmshInitialize(argc, argv);
-  gmshOptionSetNumber("General.Terminal", 1);
+  gmsh::initialize(argc, argv);
+  gmsh::option::setNumber("General.Terminal", 1);
 
-  gmshModelCreate("t16");
+  gmsh::model::add("t16");
 
   std::vector<std::pair<int, int> > ov;
   std::vector<std::vector<std::pair<int, int> > > ovv;
-  gmshModelOccAddBox(0,0,0, 1,1,1, 1);
-  gmshModelOccAddBox(0,0,0, 0.5,0.5,0.5, 2);
-  gmshModelOccBooleanDifference({{3,1}}, {{3,2}}, ov, ovv, 3);
+  gmsh::model::occ::addBox(0,0,0, 1,1,1, 1);
+  gmsh::model::occ::addBox(0,0,0, 0.5,0.5,0.5, 2);
+  gmsh::model::occ::booleanDifference({{3,1}}, {{3,2}}, ov, ovv, 3);
   double x = 0, y = 0.75, z = 0, r = 0.09 ;
   std::vector<std::pair<int, int> > holes;
   for(int t = 1; t <= 5; t++){
     x += 0.166 ;
     z += 0.166 ;
-    gmshModelOccAddSphere(x,y,z,r, 3 + t);
+    gmsh::model::occ::addSphere(x,y,z,r, 3 + t);
     holes.push_back({3, 3 + t});
   }
-  gmshModelOccBooleanFragments({{3,3}}, holes, ov, ovv);
+  gmsh::model::occ::booleanFragments({{3,3}}, holes, ov, ovv);
 
-  gmshModelOccSynchronize();
+  gmsh::model::occ::synchronize();
 
   double lcar1 = .1;
   double lcar2 = .0005;
   double lcar3 = .055;
 
-  gmshModelGetEntities(ov, 0);
-  gmshModelSetMeshSize(ov, lcar1);
+  gmsh::model::getEntities(ov, 0);
+  gmsh::model::mesh::setSize(ov, lcar1);
 
-  gmshModelGetBoundary(holes, ov, false, false, true);
-  gmshModelSetMeshSize(ov, lcar3);
+  gmsh::model::getBoundary(holes, ov, false, false, true);
+  gmsh::model::mesh::setSize(ov, lcar3);
 
   double eps = 1e-3;
-  gmshModelGetEntitiesInBoundingBox(0.5-eps, 0.5-eps, 0.5-eps,
-                                    0.5+eps, 0.5+eps, 0.5+eps, ov, 0);
-  gmshModelSetMeshSize(ov, lcar2);
+  gmsh::model::getEntitiesInBoundingBox(0.5-eps, 0.5-eps, 0.5-eps,
+                                        0.5+eps, 0.5+eps, 0.5+eps, ov, 0);
+  gmsh::model::mesh::setSize(ov, lcar2);
 
-  gmshModelMesh(3);
+  gmsh::model::mesh::generate(3);
 
-  gmshExport("t16.msh");
+  gmsh::write("t16.msh");
 
-  gmshFinalize();
+  gmsh::finalize();
   return 0;
 }
diff --git a/demos/api/t16.py b/demos/api/t16.py
index 3343f9e97827249d58a30876f21b1aa062e0e028..b5575264a2dc3049507b3928a3625efbe3cc8e13 100644
--- a/demos/api/t16.py
+++ b/demos/api/t16.py
@@ -2,50 +2,50 @@
 
 # This file reimplements gmsh/tutorial/t16.geo in Python.
 
-from gmsh import *
+import gmsh
 import math
 
-gmshInitialize()
-gmshOptionSetNumber("General.Terminal", 1)
+gmsh.initialize()
+gmsh.optionSetNumber("General.Terminal", 1)
 
-gmshModelCreate("t16")
+gmsh.modelAdd("t16")
 
-ov = PairVector(); ovv = PairVectorVector()
+ov = gmsh.PairVector(); ovv = gmsh.PairVectorVector()
 
-gmshModelOccAddBox(0,0,0, 1,1,1, 1)
-gmshModelOccAddBox(0,0,0, 0.5,0.5,0.5, 2)
-gmshModelOccBooleanDifference([(3,1)], [(3,2)], ov, ovv, 3)
+gmsh.modelOccAddBox(0,0,0, 1,1,1, 1)
+gmsh.modelOccAddBox(0,0,0, 0.5,0.5,0.5, 2)
+gmsh.modelOccBooleanDifference([(3,1)], [(3,2)], ov, ovv, 3)
 
 x = 0; y = 0.75; z = 0; r = 0.09
 
-holes = PairVector()
+holes = gmsh.PairVector()
 for t in range(1, 6):
     x += 0.166
     z += 0.166
-    gmshModelOccAddSphere(x,y,z,r, 3 + t)
+    gmsh.modelOccAddSphere(x,y,z,r, 3 + t)
     holes.append((3, 3 + t))
 
-gmshModelOccBooleanFragments([(3,3)], holes, ov, ovv)
+gmsh.modelOccBooleanFragments([(3,3)], holes, ov, ovv)
 
-gmshModelOccSynchronize()
+gmsh.modelOccSynchronize()
 
 lcar1 = .1
 lcar2 = .0005
 lcar3 = .055
 
-gmshModelGetEntities(ov, 0);
-gmshModelSetMeshSize(ov, lcar1);
+gmsh.modelGetEntities(ov, 0);
+gmsh.modelMeshSetSize(ov, lcar1);
 
-gmshModelGetBoundary(holes, ov, False, False, True);
-gmshModelSetMeshSize(ov, lcar3);
+gmsh.modelGetBoundary(holes, ov, False, False, True);
+gmsh.modelMeshSetSize(ov, lcar3);
 
 eps = 1e-3
-gmshModelGetEntitiesInBoundingBox(0.5-eps, 0.5-eps, 0.5-eps,
+gmsh.modelGetEntitiesInBoundingBox(0.5-eps, 0.5-eps, 0.5-eps,
                                   0.5+eps, 0.5+eps, 0.5+eps, ov, 0)
-gmshModelSetMeshSize(ov, lcar2)
+gmsh.modelMeshSetSize(ov, lcar2)
 
-gmshModelMesh(3)
+gmsh.modelMeshGenerate(3)
 
-gmshExport("t16.msh")
+gmsh.write("t16.msh")
 
-gmshFinalize()
+gmsh.finalize()
diff --git a/demos/api/t2.cpp b/demos/api/t2.cpp
index 85666ba8d5b7d5ccabffd87d2160edfcc951c7a2..094e34fbce4554a2e8d84ef7aa9b29f148bc89a9 100644
--- a/demos/api/t2.cpp
+++ b/demos/api/t2.cpp
@@ -3,108 +3,111 @@
 
 #include <gmsh.h>
 
+// make all function in the gmsh namespace directly available
+using namespace gmsh;
+
 int main(int argc, char **argv)
 {
   // If argc/argv are passed, Gmsh will parse the commandline in the same way as
   // the standalone Gmsh code.
-  gmshInitialize(argc, argv);
-  gmshOptionSetNumber("General.Terminal", 1);
+  initialize(argc, argv);
+  option::setNumber("General.Terminal", 1);
 
-  gmshModelCreate("t2");
+  model::add("t2");
 
   // Copied from t1.cpp...
   double lc = 1e-2;
-  gmshModelGeoAddPoint(0, 0, 0, lc, 1);
-  gmshModelGeoAddPoint(.1, 0,  0, lc, 2);
-  gmshModelGeoAddPoint(.1, .3, 0, lc, 3);
-  gmshModelGeoAddPoint(0,  .3, 0, lc, 4);
-  gmshModelGeoAddLine(1, 2, 1);
-  gmshModelGeoAddLine(3, 2, 2);
-  gmshModelGeoAddLine(3, 4, 3);
-  gmshModelGeoAddLine(4, 1, 4);
-  gmshModelGeoAddLineLoop({4, 1, -2, 3}, 1);
-  gmshModelGeoAddPlaneSurface({1}, 1);
-  gmshModelAddPhysicalGroup(0, {1, 2}, 1);
-  gmshModelAddPhysicalGroup(1, {1, 2}, 2);
-  gmshModelAddPhysicalGroup(2, {1}, 6);
-  gmshModelSetPhysicalName(2, 6, "My surface");
+  model::geo::addPoint(0, 0, 0, lc, 1);
+  model::geo::addPoint(.1, 0,  0, lc, 2);
+  model::geo::addPoint(.1, .3, 0, lc, 3);
+  model::geo::addPoint(0,  .3, 0, lc, 4);
+  model::geo::addLine(1, 2, 1);
+  model::geo::addLine(3, 2, 2);
+  model::geo::addLine(3, 4, 3);
+  model::geo::addLine(4, 1, 4);
+  model::geo::addLineLoop({4, 1, -2, 3}, 1);
+  model::geo::addPlaneSurface({1}, 1);
+  model::addPhysicalGroup(0, {1, 2}, 1);
+  model::addPhysicalGroup(1, {1, 2}, 2);
+  model::addPhysicalGroup(2, {1}, 6);
+  model::setPhysicalName(2, 6, "My surface");
   // ...end of copy
 
-  gmshModelGeoAddPoint(0, .4, 0, lc, 5);
-  gmshModelGeoAddLine(4, 5, 5);
+  model::geo::addPoint(0, .4, 0, lc, 5);
+  model::geo::addLine(4, 5, 5);
 
   // Geometrical transformations take a vector of pairs of integers as first
   // argument, which contains the list of entities, represented by (dimension,
   // tag) pairs. Here we thus translate point 3 (dimension=0, tag=3), by
   // dx=-0.05, dy=0, dz=0.
-  gmshModelGeoTranslate({{0, 3}}, -0.05, 0, 0);
+  model::geo::translate({{0, 3}}, -0.05, 0, 0);
 
   // The "Duplicata" functionality in .geo files is handled by
-  // gmshModelGeoCopy(), which takes a vector of (dim, tag) pairs as input, and
+  // model::geo::copy(), which takes a vector of (dim, tag) pairs as input, and
   // returns another vector of (dim, tag) pairs.
   std::vector<std::pair<int, int> > ov;
-  gmshModelGeoCopy({{0, 3}}, ov);
-  gmshModelGeoTranslate(ov, 0, 0.1, 0);
+  model::geo::copy({{0, 3}}, ov);
+  model::geo::translate(ov, 0, 0.1, 0);
 
-  gmshModelGeoAddLine(3, ov[0].second, 7);
-  gmshModelGeoAddLine(ov[0].second, 5, 8);
-  gmshModelGeoAddLineLoop({5,-8,-7,3}, 10);
-  gmshModelGeoAddPlaneSurface({10}, 11);
+  model::geo::addLine(3, ov[0].second, 7);
+  model::geo::addLine(ov[0].second, 5, 8);
+  model::geo::addLineLoop({5,-8,-7,3}, 10);
+  model::geo::addPlaneSurface({10}, 11);
 
-  gmshModelGeoCopy({{2, 1}, {2, 11}}, ov);
-  gmshModelGeoTranslate(ov, 0.12, 0, 0);
+  model::geo::copy({{2, 1}, {2, 11}}, ov);
+  model::geo::translate(ov, 0.12, 0, 0);
 
   std::printf("New surfaces '%d' and '%d'\n", ov[0].second, ov[1].second);
 
-  gmshModelGeoAddPoint(0., 0.3, 0.13, lc, 100);
-  gmshModelGeoAddPoint(0.08, 0.3, 0.1, lc, 101);
-  gmshModelGeoAddPoint(0.08, 0.4, 0.1, lc, 102);
-  gmshModelGeoAddPoint(0., 0.4, 0.13, lc, 103);
-
-  gmshModelGeoAddLine(4, 100, 110);
-  gmshModelGeoAddLine(3, 101, 111);
-  gmshModelGeoAddLine(6, 102, 112);
-  gmshModelGeoAddLine(5, 103, 113);
-  gmshModelGeoAddLine(103, 100, 114);
-  gmshModelGeoAddLine(100, 101, 115);
-  gmshModelGeoAddLine(101, 102, 116);
-  gmshModelGeoAddLine(102, 103, 117);
-
-  gmshModelGeoAddLineLoop({115, -111, 3, 110}, 118);
-  gmshModelGeoAddPlaneSurface({118}, 119);
-  gmshModelGeoAddLineLoop({111, 116, -112, -7}, 120);
-  gmshModelGeoAddPlaneSurface({120}, 121);
-  gmshModelGeoAddLineLoop({112, 117, -113, -8}, 122);
-  gmshModelGeoAddPlaneSurface({122}, 123);
-  gmshModelGeoAddLineLoop({114, -110, 5, 113}, 124);
-  gmshModelGeoAddPlaneSurface({124}, 125);
-  gmshModelGeoAddLineLoop({115, 116, 117, 114}, 126);
-  gmshModelGeoAddPlaneSurface({126}, 127);
+  model::geo::addPoint(0., 0.3, 0.13, lc, 100);
+  model::geo::addPoint(0.08, 0.3, 0.1, lc, 101);
+  model::geo::addPoint(0.08, 0.4, 0.1, lc, 102);
+  model::geo::addPoint(0., 0.4, 0.13, lc, 103);
+
+  model::geo::addLine(4, 100, 110);
+  model::geo::addLine(3, 101, 111);
+  model::geo::addLine(6, 102, 112);
+  model::geo::addLine(5, 103, 113);
+  model::geo::addLine(103, 100, 114);
+  model::geo::addLine(100, 101, 115);
+  model::geo::addLine(101, 102, 116);
+  model::geo::addLine(102, 103, 117);
+
+  model::geo::addLineLoop({115, -111, 3, 110}, 118);
+  model::geo::addPlaneSurface({118}, 119);
+  model::geo::addLineLoop({111, 116, -112, -7}, 120);
+  model::geo::addPlaneSurface({120}, 121);
+  model::geo::addLineLoop({112, 117, -113, -8}, 122);
+  model::geo::addPlaneSurface({122}, 123);
+  model::geo::addLineLoop({114, -110, 5, 113}, 124);
+  model::geo::addPlaneSurface({124}, 125);
+  model::geo::addLineLoop({115, 116, 117, 114}, 126);
+  model::geo::addPlaneSurface({126}, 127);
 
   // The API to create surface loops ("shells") and volumes is similar to the
   // one used to create line loops and surfaces.
-  gmshModelGeoAddSurfaceLoop({127, 119, 121, 123, 125, 11}, 128);
-  gmshModelGeoAddVolume({128}, 129);
+  model::geo::addSurfaceLoop({127, 119, 121, 123, 125, 11}, 128);
+  model::geo::addVolume({128}, 129);
 
   // Extrusion works as expected, by providing a vector of (dim, tag) pairs as
   // input, the translation vector, and a vector of (dim, tag) pairs as output.
   std::vector<std::pair<int, int> > ov2;
-  gmshModelGeoExtrude({ov[1]}, 0, 0, 0.12, ov2);
+  model::geo::extrude({ov[1]}, 0, 0, 0.12, ov2);
 
   // Mesh sizes associated to geometrical points can be set by passing a vector
   // of (dim, tag) pairs for the corresponding points.
-  gmshModelGeoSetMeshSize({{0,103}, {0,105}, {0,109}, {0,102}, {0,28},
-                           {0, 24}, {0,6}, {0,5}}, lc * 3);
+  model::geo::mesh::setSize({{0,103}, {0,105}, {0,109}, {0,102}, {0,28},
+                            {0, 24}, {0,6}, {0,5}}, lc * 3);
 
-  gmshModelAddPhysicalGroup(3, {129,130}, 1);
-  gmshModelSetPhysicalName(3, 1, "The volume");
+  model::addPhysicalGroup(3, {129,130}, 1);
+  model::setPhysicalName(3, 1, "The volume");
 
-  gmshModelGeoSynchronize();
+  model::geo::synchronize();
 
-  gmshModelMesh(3);
+  model::mesh::generate(3);
 
-  gmshExport("t2.msh");
+  write("t2.msh");
 
-  gmshFinalize();
+  finalize();
   return 0;
 }
diff --git a/demos/api/t2.py b/demos/api/t2.py
index 1e6f9857ddc8e6dbb447165fb039827dfe3507f7..e1d6e32a7a5b93ae79cc8a6151060c838b19448c 100644
--- a/demos/api/t2.py
+++ b/demos/api/t2.py
@@ -3,110 +3,110 @@
 # This file reimplements gmsh/tutorial/t2.geo in Python. Comments focus on the new
 # API functions used, compared to the ones introduced in t1.py.
 
-from gmsh import *
+import gmsh
 import sys
 
 # If sys.argv is passed, Gmsh will parse the commandline in the same way as the
 # standalone Gmsh code.
-gmshInitialize(sys.argv)
+gmsh.initialize(sys.argv)
 
-gmshOptionSetNumber("General.Terminal", 1)
+gmsh.optionSetNumber("General.Terminal", 1)
 
-gmshModelCreate("t2")
+gmsh.modelAdd("t2")
 
 # Copied from t1.py...
 lc = 1e-2
-gmshModelGeoAddPoint(0, 0, 0, lc, 1)
-gmshModelGeoAddPoint(.1, 0,  0, lc, 2)
-gmshModelGeoAddPoint(.1, .3, 0, lc, 3)
-gmshModelGeoAddPoint(0, .3, 0, lc, 4)
-gmshModelGeoAddLine(1, 2, 1)
-gmshModelGeoAddLine(3, 2, 2)
-gmshModelGeoAddLine(3, 4, 3)
-gmshModelGeoAddLine(4, 1, 4)
-gmshModelGeoAddLineLoop([4, 1, -2, 3], 1)
-gmshModelGeoAddPlaneSurface([1], 1)
-gmshModelAddPhysicalGroup(0, [1, 2], 1)
-gmshModelAddPhysicalGroup(1, [1, 2], 2)
-gmshModelAddPhysicalGroup(2, [1], 6)
-gmshModelSetPhysicalName(2, 6, "My surface")
+gmsh.modelGeoAddPoint(0, 0, 0, lc, 1)
+gmsh.modelGeoAddPoint(.1, 0,  0, lc, 2)
+gmsh.modelGeoAddPoint(.1, .3, 0, lc, 3)
+gmsh.modelGeoAddPoint(0, .3, 0, lc, 4)
+gmsh.modelGeoAddLine(1, 2, 1)
+gmsh.modelGeoAddLine(3, 2, 2)
+gmsh.modelGeoAddLine(3, 4, 3)
+gmsh.modelGeoAddLine(4, 1, 4)
+gmsh.modelGeoAddLineLoop([4, 1, -2, 3], 1)
+gmsh.modelGeoAddPlaneSurface([1], 1)
+gmsh.modelAddPhysicalGroup(0, [1, 2], 1)
+gmsh.modelAddPhysicalGroup(1, [1, 2], 2)
+gmsh.modelAddPhysicalGroup(2, [1], 6)
+gmsh.modelSetPhysicalName(2, 6, "My surface")
 # ...end of copy
 
-gmshModelGeoAddPoint(0, .4, 0, lc, 5)
-gmshModelGeoAddLine(4, 5, 5)
+gmsh.modelGeoAddPoint(0, .4, 0, lc, 5)
+gmsh.modelGeoAddLine(4, 5, 5)
 
 # Geometrical transformations take a vector of pairs of integers as first
 # argument, which contains the list of entities, represented by (dimension, tag)
 # pairs. Here we thus translate point 3 (dimension=0, tag=3), by dx=-0.05, dy=0,
 # dz=0.
-gmshModelGeoTranslate([(0, 3)], -0.05, 0, 0)
+gmsh.modelGeoTranslate([(0, 3)], -0.05, 0, 0)
 
 # The "Duplicata" functionality in .geo files is handled by
-# gmshModelGeoCopy(), which takes a vector of (dim, tag) pairs as input, and
+# gmsh.modelGeoCopy(), which takes a vector of (dim, tag) pairs as input, and
 # returns another vector of (dim, tag) pairs.
 
-ov = PairVector()
-gmshModelGeoCopy([(0, 3)], ov)
-gmshModelGeoTranslate(ov, 0, 0.1, 0)
+ov = gmsh.PairVector()
+gmsh.modelGeoCopy([(0, 3)], ov)
+gmsh.modelGeoTranslate(ov, 0, 0.1, 0)
 
-gmshModelGeoAddLine(3, ov[0][1], 7)
-gmshModelGeoAddLine(ov[0][1], 5, 8)
-gmshModelGeoAddLineLoop([5,-8,-7,3], 10)
-gmshModelGeoAddPlaneSurface([10], 11)
+gmsh.modelGeoAddLine(3, ov[0][1], 7)
+gmsh.modelGeoAddLine(ov[0][1], 5, 8)
+gmsh.modelGeoAddLineLoop([5,-8,-7,3], 10)
+gmsh.modelGeoAddPlaneSurface([10], 11)
 
-gmshModelGeoCopy([(2, 1), (2, 11)], ov)
-gmshModelGeoTranslate(ov, 0.12, 0, 0)
+gmsh.modelGeoCopy([(2, 1), (2, 11)], ov)
+gmsh.modelGeoTranslate(ov, 0.12, 0, 0)
 
 print "New surfaces " + str(ov[0][1]) + " and " + str(ov[1][1])
 
-gmshModelGeoAddPoint(0., 0.3, 0.13, lc, 100)
-gmshModelGeoAddPoint(0.08, 0.3, 0.1, lc, 101)
-gmshModelGeoAddPoint(0.08, 0.4, 0.1, lc, 102)
-gmshModelGeoAddPoint(0., 0.4, 0.13, lc, 103)
-
-gmshModelGeoAddLine(4, 100, 110)
-gmshModelGeoAddLine(3, 101, 111)
-gmshModelGeoAddLine(6, 102, 112)
-gmshModelGeoAddLine(5, 103, 113)
-gmshModelGeoAddLine(103, 100, 114)
-gmshModelGeoAddLine(100, 101, 115)
-gmshModelGeoAddLine(101, 102, 116)
-gmshModelGeoAddLine(102, 103, 117)
-
-gmshModelGeoAddLineLoop([115, -111, 3, 110], 118)
-gmshModelGeoAddPlaneSurface([118], 119)
-gmshModelGeoAddLineLoop([111, 116, -112, -7], 120)
-gmshModelGeoAddPlaneSurface([120], 121)
-gmshModelGeoAddLineLoop([112, 117, -113, -8], 122)
-gmshModelGeoAddPlaneSurface([122], 123)
-gmshModelGeoAddLineLoop([114, -110, 5, 113], 124)
-gmshModelGeoAddPlaneSurface([124], 125)
-gmshModelGeoAddLineLoop([115, 116, 117, 114], 126)
-gmshModelGeoAddPlaneSurface([126], 127)
+gmsh.modelGeoAddPoint(0., 0.3, 0.13, lc, 100)
+gmsh.modelGeoAddPoint(0.08, 0.3, 0.1, lc, 101)
+gmsh.modelGeoAddPoint(0.08, 0.4, 0.1, lc, 102)
+gmsh.modelGeoAddPoint(0., 0.4, 0.13, lc, 103)
+
+gmsh.modelGeoAddLine(4, 100, 110)
+gmsh.modelGeoAddLine(3, 101, 111)
+gmsh.modelGeoAddLine(6, 102, 112)
+gmsh.modelGeoAddLine(5, 103, 113)
+gmsh.modelGeoAddLine(103, 100, 114)
+gmsh.modelGeoAddLine(100, 101, 115)
+gmsh.modelGeoAddLine(101, 102, 116)
+gmsh.modelGeoAddLine(102, 103, 117)
+
+gmsh.modelGeoAddLineLoop([115, -111, 3, 110], 118)
+gmsh.modelGeoAddPlaneSurface([118], 119)
+gmsh.modelGeoAddLineLoop([111, 116, -112, -7], 120)
+gmsh.modelGeoAddPlaneSurface([120], 121)
+gmsh.modelGeoAddLineLoop([112, 117, -113, -8], 122)
+gmsh.modelGeoAddPlaneSurface([122], 123)
+gmsh.modelGeoAddLineLoop([114, -110, 5, 113], 124)
+gmsh.modelGeoAddPlaneSurface([124], 125)
+gmsh.modelGeoAddLineLoop([115, 116, 117, 114], 126)
+gmsh.modelGeoAddPlaneSurface([126], 127)
 
 # The API to create surface loops ("shells") and volumes is similar to the
 # one used to create line loops and surfaces.
-gmshModelGeoAddSurfaceLoop([127, 119, 121, 123, 125, 11], 128)
-gmshModelGeoAddVolume([128], 129)
+gmsh.modelGeoAddSurfaceLoop([127, 119, 121, 123, 125, 11], 128)
+gmsh.modelGeoAddVolume([128], 129)
 
 # Extrusion works as expected, by providing a vector of (dim, tag) pairs as
 # input, the translation vector, and a vector of (dim, tag) pairs as output.
-ov2 = PairVector()
-gmshModelGeoExtrude([ov[1]], 0, 0, 0.12, ov2)
+ov2 = gmsh.PairVector()
+gmsh.modelGeoExtrude([ov[1]], 0, 0, 0.12, ov2)
 
 # Mesh sizes associated to geometrical points can be set by passing a vector of
 # (dim, tag) pairs for the corresponding points.
 
-gmshModelGeoSetMeshSize([(0,103), (0,105), (0,109), (0,102), (0,28),
+gmsh.modelGeoMeshSetSize([(0,103), (0,105), (0,109), (0,102), (0,28),
                          (0, 24), (0,6), (0,5)], lc * 3)
 
-gmshModelAddPhysicalGroup(3, [129,130], 1)
-gmshModelSetPhysicalName(3, 1, "The volume")
+gmsh.modelAddPhysicalGroup(3, [129,130], 1)
+gmsh.modelSetPhysicalName(3, 1, "The volume")
 
-gmshModelGeoSynchronize()
+gmsh.modelGeoSynchronize()
 
-gmshModelMesh(3)
+gmsh.modelMeshGenerate(3)
 
-gmshExport("t2.msh")
+gmsh.write("t2.msh")
 
-gmshFinalize()
+gmsh.finalize()
diff --git a/demos/api/t3.cpp b/demos/api/t3.cpp
index cf60d3ad810e4579639bb142cf02f974a9b2f780..adbc952dbe19f8fad89ad9641cb29b85576e581d 100644
--- a/demos/api/t3.cpp
+++ b/demos/api/t3.cpp
@@ -3,29 +3,31 @@
 #include <cmath>
 #include <gmsh.h>
 
+using namespace gmsh;
+
 int main(int argc, char **argv)
 {
-  gmshInitialize(argc, argv);
-  gmshOptionSetNumber("General.Terminal", 1);
+  initialize(argc, argv);
+  option::setNumber("General.Terminal", 1);
 
-  gmshModelCreate("t3");
+  model::add("t3");
 
   // Copied from t1.cpp...
   double lc = 1e-2;
-  gmshModelGeoAddPoint(0, 0, 0, lc, 1);
-  gmshModelGeoAddPoint(.1, 0,  0, lc, 2);
-  gmshModelGeoAddPoint(.1, .3, 0, lc, 3);
-  gmshModelGeoAddPoint(0,  .3, 0, lc, 4);
-  gmshModelGeoAddLine(1, 2, 1);
-  gmshModelGeoAddLine(3, 2, 2);
-  gmshModelGeoAddLine(3, 4, 3);
-  gmshModelGeoAddLine(4, 1, 4);
-  gmshModelGeoAddLineLoop({4, 1, -2, 3}, 1);
-  gmshModelGeoAddPlaneSurface({1}, 1);
-  gmshModelAddPhysicalGroup(0, {1, 2}, 1);
-  gmshModelAddPhysicalGroup(1, {1, 2}, 2);
-  gmshModelAddPhysicalGroup(2, {1}, 6);
-  gmshModelSetPhysicalName(2, 6, "My surface");
+  model::geo::addPoint(0, 0, 0, lc, 1);
+  model::geo::addPoint(.1, 0,  0, lc, 2);
+  model::geo::addPoint(.1, .3, 0, lc, 3);
+  model::geo::addPoint(0,  .3, 0, lc, 4);
+  model::geo::addLine(1, 2, 1);
+  model::geo::addLine(3, 2, 2);
+  model::geo::addLine(3, 4, 3);
+  model::geo::addLine(4, 1, 4);
+  model::geo::addLineLoop({4, 1, -2, 3}, 1);
+  model::geo::addPlaneSurface({1}, 1);
+  model::addPhysicalGroup(0, {1, 2}, 1);
+  model::addPhysicalGroup(1, {1, 2}, 2);
+  model::addPhysicalGroup(2, {1}, 6);
+  model::setPhysicalName(2, 6, "My surface");
   // ...end of copy
 
   double h = 0.1, angle = 90.;
@@ -34,21 +36,22 @@ int main(int argc, char **argv)
   // Extruding the mesh in addition to the geometry works as in .geo files: the
   // number of elements for each layer and the (end) height of each layer are
   // specified in two vectors.
-  gmshModelGeoExtrude({{2,1}}, 0, 0, h, ov, {8,2}, {0.5,1});
+  model::geo::extrude({{2,1}}, 0, 0, h, ov, {8,2}, {0.5,1});
 
   // Rotational and twisted extrusions are available as well with the built-in
   // CAD kernel. The last (optional) argument for the Extrude/Revolve/Twist
   // commands specified whether the extruded mesh should be recombined or not.
-  gmshModelGeoRevolve({{2,28}}, -0.1,0,0.1, 0,1,0, -M_PI/2, ov, {7});
-  gmshModelGeoTwist({{2,50}}, 0,0.15,0.25, -2*h,0,0, 1,0,0, angle*M_PI/180.,
+  model::geo::revolve({{2,28}}, -0.1,0,0.1, 0,1,0, -M_PI/2, ov, {7});
+  model::geo::twist({{2,50}}, 0,0.15,0.25, -2*h,0,0, 1,0,0, angle*M_PI/180.,
                     ov, {10}, {}, true);
 
-  gmshModelAddPhysicalGroup(3, {1, 2, ov[1].second}, 101);
+  model::geo::synchronize();
+
+  model::addPhysicalGroup(3, {1, 2, ov[1].second}, 101);
 
-  gmshModelGeoSynchronize();
-  gmshModelMesh(3);
-  gmshExport("t3.msh");
-  gmshFinalize();
+  model::mesh::generate(3);
+  write("t3.msh");
+  finalize();
 
   return 0;
 }
diff --git a/demos/api/t3.py b/demos/api/t3.py
index 4a948910dd09552a4e7a7801c050465bbce00f33..86510155454e82304477f9fe13bec73128646b7c 100644
--- a/demos/api/t3.py
+++ b/demos/api/t3.py
@@ -2,52 +2,52 @@
 
 # This files reimplements gmsh/tutorial/t3.geo in Python.
 
-from gmsh import *
+import gmsh
 import math
 
-gmshInitialize()
-gmshOptionSetNumber("General.Terminal", 1)
+gmsh.initialize()
+gmsh.optionSetNumber("General.Terminal", 1)
 
-gmshModelCreate("t3")
+gmsh.modelAdd("t3")
 
 # Copied from t1.py...
 lc = 1e-2
-gmshModelGeoAddPoint(0, 0, 0, lc, 1)
-gmshModelGeoAddPoint(.1, 0,  0, lc, 2)
-gmshModelGeoAddPoint(.1, .3, 0, lc, 3)
-gmshModelGeoAddPoint(0, .3, 0, lc, 4)
-gmshModelGeoAddLine(1, 2, 1)
-gmshModelGeoAddLine(3, 2, 2)
-gmshModelGeoAddLine(3, 4, 3)
-gmshModelGeoAddLine(4, 1, 4)
-gmshModelGeoAddLineLoop([4, 1, -2, 3], 1)
-gmshModelGeoAddPlaneSurface([1], 1)
-gmshModelAddPhysicalGroup(0, [1, 2], 1)
-gmshModelAddPhysicalGroup(1, [1, 2], 2)
-gmshModelAddPhysicalGroup(2, [1], 6)
-gmshModelSetPhysicalName(2, 6, "My surface")
+gmsh.modelGeoAddPoint(0, 0, 0, lc, 1)
+gmsh.modelGeoAddPoint(.1, 0,  0, lc, 2)
+gmsh.modelGeoAddPoint(.1, .3, 0, lc, 3)
+gmsh.modelGeoAddPoint(0, .3, 0, lc, 4)
+gmsh.modelGeoAddLine(1, 2, 1)
+gmsh.modelGeoAddLine(3, 2, 2)
+gmsh.modelGeoAddLine(3, 4, 3)
+gmsh.modelGeoAddLine(4, 1, 4)
+gmsh.modelGeoAddLineLoop([4, 1, -2, 3], 1)
+gmsh.modelGeoAddPlaneSurface([1], 1)
+gmsh.modelAddPhysicalGroup(0, [1, 2], 1)
+gmsh.modelAddPhysicalGroup(1, [1, 2], 2)
+gmsh.modelAddPhysicalGroup(2, [1], 6)
+gmsh.modelSetPhysicalName(2, 6, "My surface")
 # ...end of copy
 
 h = 0.1
 angle = 90.
 
-ov = PairVector()
+ov = gmsh.PairVector()
   
 # Extruding the mesh in addition to the geometry works as in .geo files: the
 # number of elements for each layer and the (end) height of each layer are
 # specified in two vectors.
-gmshModelGeoExtrude([(2,1)], 0, 0, h, ov, [8,2], [0.5,1])
+gmsh.modelGeoExtrude([(2,1)], 0, 0, h, ov, [8,2], [0.5,1])
 
 #/ Rotational and twisted extrusions are available as well with the built-in CAD
 # kernel. The last (optional) argument for the Extrude/Revolve/Twist commands
 # specified whether the extruded mesh should be recombined or not.
-gmshModelGeoRevolve([(2,28)], -0.1,0,0.1, 0,1,0, -math.pi/2, ov, [7])
-gmshModelGeoTwist([(2,50)], 0,0.15,0.25, -2*h,0,0, 1,0,0, angle*math.pi/180.,
+gmsh.modelGeoRevolve([(2,28)], -0.1,0,0.1, 0,1,0, -math.pi/2, ov, [7])
+gmsh.modelGeoTwist([(2,50)], 0,0.15,0.25, -2*h,0,0, 1,0,0, angle*math.pi/180.,
                   ov, [10], [], True)
 
-gmshModelAddPhysicalGroup(3, [1, 2, ov[1][1]], 101)
+gmsh.modelAddPhysicalGroup(3, [1, 2, ov[1][1]], 101)
 
-gmshModelGeoSynchronize()
-gmshModelMesh(3)
-gmshExport("t3.msh")
-gmshFinalize()
+gmsh.modelGeoSynchronize()
+gmsh.modelMeshGenerate(3)
+gmsh.write("t3.msh")
+gmsh.finalize()
diff --git a/demos/api/t4.cpp b/demos/api/t4.cpp
index 72cd55c56108eba367fafca57075b9493036f95f..3302979b2ce3481e3aecf4a192c168926ec1a5cf 100644
--- a/demos/api/t4.cpp
+++ b/demos/api/t4.cpp
@@ -3,14 +3,16 @@
 #include <math.h>
 #include <gmsh.h>
 
+using namespace gmsh;
+
 double hypoth(double a, double b){ return sqrt(a * a + b * b); }
 
 int main(int argc, char **argv)
 {
-  gmshInitialize(argc, argv);
-  gmshOptionSetNumber("General.Terminal", 1);
+  initialize(argc, argv);
+  option::setNumber("General.Terminal", 1);
 
-  gmshModelCreate("t4");
+  model::add("t4");
 
   double cm = 1e-02;
   double e1 = 4.5 * cm, e2 = 6 * cm / 2, e3 =  5 * cm / 2;
@@ -22,63 +24,63 @@ int main(int argc, char **argv)
   double ccos = (-h5*R1 + e2 * hypot(h5, hypot(e2, R1))) / (h5*h5 + e2*e2);
   double ssin = sqrt(1 - ccos*ccos);
 
-  gmshModelGeoAddPoint(-e1-e2, 0    , 0, Lc1, 1);
-  gmshModelGeoAddPoint(-e1-e2, h1   , 0, Lc1, 2);
-  gmshModelGeoAddPoint(-e3-r , h1   , 0, Lc2, 3);
-  gmshModelGeoAddPoint(-e3-r , h1+r , 0, Lc2, 4);
-  gmshModelGeoAddPoint(-e3   , h1+r , 0, Lc2, 5);
-  gmshModelGeoAddPoint(-e3   , h1+h2, 0, Lc1, 6);
-  gmshModelGeoAddPoint( e3   , h1+h2, 0, Lc1, 7);
-  gmshModelGeoAddPoint( e3   , h1+r , 0, Lc2, 8);
-  gmshModelGeoAddPoint( e3+r , h1+r , 0, Lc2, 9);
-  gmshModelGeoAddPoint( e3+r , h1   , 0, Lc2, 10);
-  gmshModelGeoAddPoint( e1+e2, h1   , 0, Lc1, 11);
-  gmshModelGeoAddPoint( e1+e2, 0    , 0, Lc1, 12);
-  gmshModelGeoAddPoint( e2   , 0    , 0, Lc1, 13);
-
-  gmshModelGeoAddPoint( R1 / ssin, h5+R1*ccos, 0, Lc2, 14);
-  gmshModelGeoAddPoint( 0        , h5        , 0, Lc2, 15);
-  gmshModelGeoAddPoint(-R1 / ssin, h5+R1*ccos, 0, Lc2, 16);
-  gmshModelGeoAddPoint(-e2       , 0.0       , 0, Lc1, 17);
-
-  gmshModelGeoAddPoint(-R2 , h1+h3   , 0, Lc2, 18);
-  gmshModelGeoAddPoint(-R2 , h1+h3+h4, 0, Lc2, 19);
-  gmshModelGeoAddPoint( 0  , h1+h3+h4, 0, Lc2, 20);
-  gmshModelGeoAddPoint( R2 , h1+h3+h4, 0, Lc2, 21);
-  gmshModelGeoAddPoint( R2 , h1+h3   , 0, Lc2, 22);
-  gmshModelGeoAddPoint( 0  , h1+h3   , 0, Lc2, 23);
-
-  gmshModelGeoAddPoint(0, h1+h3+h4+R2, 0, Lc2, 24);
-  gmshModelGeoAddPoint(0, h1+h3-R2,    0, Lc2, 25);
-
-  gmshModelGeoAddLine(1 , 17, 1);
-  gmshModelGeoAddLine(17, 16, 2);
-
-  gmshModelGeoAddCircleArc(14,15,16, 3);
-  gmshModelGeoAddLine(14,13, 4);
-  gmshModelGeoAddLine(13,12, 5);
-  gmshModelGeoAddLine(12,11, 6);
-  gmshModelGeoAddLine(11,10, 7);
-  gmshModelGeoAddCircleArc(8,9,10, 8);
-  gmshModelGeoAddLine(8,7, 9);
-  gmshModelGeoAddLine(7,6, 10);
-  gmshModelGeoAddLine(6,5, 11);
-  gmshModelGeoAddCircleArc(3,4,5, 12);
-  gmshModelGeoAddLine(3,2, 13);
-  gmshModelGeoAddLine(2,1, 14);
-  gmshModelGeoAddLine(18,19, 15);
-  gmshModelGeoAddCircleArc(21,20,24, 16);
-  gmshModelGeoAddCircleArc(24,20,19, 17);
-  gmshModelGeoAddCircleArc(18,23,25, 18);
-  gmshModelGeoAddCircleArc(25,23,22, 19);
-  gmshModelGeoAddLine(21,22, 20);
-
-  gmshModelGeoAddLineLoop({17,-15,18,19,-20,16}, 21);
-  gmshModelGeoAddPlaneSurface({21}, 22);
-  gmshModelGeoAddLineLoop({11,-12,13,14,1,2,-3,4,5,6,7,-8,9,10}, 23);
+  model::geo::addPoint(-e1-e2, 0    , 0, Lc1, 1);
+  model::geo::addPoint(-e1-e2, h1   , 0, Lc1, 2);
+  model::geo::addPoint(-e3-r , h1   , 0, Lc2, 3);
+  model::geo::addPoint(-e3-r , h1+r , 0, Lc2, 4);
+  model::geo::addPoint(-e3   , h1+r , 0, Lc2, 5);
+  model::geo::addPoint(-e3   , h1+h2, 0, Lc1, 6);
+  model::geo::addPoint( e3   , h1+h2, 0, Lc1, 7);
+  model::geo::addPoint( e3   , h1+r , 0, Lc2, 8);
+  model::geo::addPoint( e3+r , h1+r , 0, Lc2, 9);
+  model::geo::addPoint( e3+r , h1   , 0, Lc2, 10);
+  model::geo::addPoint( e1+e2, h1   , 0, Lc1, 11);
+  model::geo::addPoint( e1+e2, 0    , 0, Lc1, 12);
+  model::geo::addPoint( e2   , 0    , 0, Lc1, 13);
+
+  model::geo::addPoint( R1 / ssin, h5+R1*ccos, 0, Lc2, 14);
+  model::geo::addPoint( 0        , h5        , 0, Lc2, 15);
+  model::geo::addPoint(-R1 / ssin, h5+R1*ccos, 0, Lc2, 16);
+  model::geo::addPoint(-e2       , 0.0       , 0, Lc1, 17);
+
+  model::geo::addPoint(-R2 , h1+h3   , 0, Lc2, 18);
+  model::geo::addPoint(-R2 , h1+h3+h4, 0, Lc2, 19);
+  model::geo::addPoint( 0  , h1+h3+h4, 0, Lc2, 20);
+  model::geo::addPoint( R2 , h1+h3+h4, 0, Lc2, 21);
+  model::geo::addPoint( R2 , h1+h3   , 0, Lc2, 22);
+  model::geo::addPoint( 0  , h1+h3   , 0, Lc2, 23);
+
+  model::geo::addPoint(0, h1+h3+h4+R2, 0, Lc2, 24);
+  model::geo::addPoint(0, h1+h3-R2,    0, Lc2, 25);
+
+  model::geo::addLine(1 , 17, 1);
+  model::geo::addLine(17, 16, 2);
+
+  model::geo::addCircleArc(14,15,16, 3);
+  model::geo::addLine(14,13, 4);
+  model::geo::addLine(13,12, 5);
+  model::geo::addLine(12,11, 6);
+  model::geo::addLine(11,10, 7);
+  model::geo::addCircleArc(8,9,10, 8);
+  model::geo::addLine(8,7, 9);
+  model::geo::addLine(7,6, 10);
+  model::geo::addLine(6,5, 11);
+  model::geo::addCircleArc(3,4,5, 12);
+  model::geo::addLine(3,2, 13);
+  model::geo::addLine(2,1, 14);
+  model::geo::addLine(18,19, 15);
+  model::geo::addCircleArc(21,20,24, 16);
+  model::geo::addCircleArc(24,20,19, 17);
+  model::geo::addCircleArc(18,23,25, 18);
+  model::geo::addCircleArc(25,23,22, 19);
+  model::geo::addLine(21,22, 20);
+
+  model::geo::addLineLoop({17,-15,18,19,-20,16}, 21);
+  model::geo::addPlaneSurface({21}, 22);
+  model::geo::addLineLoop({11,-12,13,14,1,2,-3,4,5,6,7,-8,9,10}, 23);
 
   // A surface with one hole is specified using 2 line loops:
-  gmshModelGeoAddPlaneSurface({23,21}, 24);
+  model::geo::addPlaneSurface({23,21}, 24);
 
   // FIXME: this will be implemented through the gmshView API
   /*
@@ -92,12 +94,12 @@ int main(int argc, char **argv)
   };
   */
 
-  gmshModelGeoSynchronize();
+  model::geo::synchronize();
 
-  gmshModelMesh(2);
+  model::mesh::generate(2);
 
-  gmshExport("t4.msh");
+  write("t4.msh");
 
-  gmshFinalize();
+  finalize();
   return 0;
 }
diff --git a/demos/api/t4.py b/demos/api/t4.py
index 3e442c83d9d56acf0ba403a238ef35086187501c..f3acf82159ab78383819a0a46e5d5f1e10efcd29 100644
--- a/demos/api/t4.py
+++ b/demos/api/t4.py
@@ -1,12 +1,12 @@
 # This file reimplements gmsh/tutorial/t4.geo in Python.
 
-from gmsh import *
+import gmsh
 import math
 
-gmshInitialize()
-gmshOptionSetNumber("General.Terminal", 1)
+gmsh.initialize()
+gmsh.optionSetNumber("General.Terminal", 1)
 
-gmshModelCreate("t4")
+gmsh.modelAdd("t4")
 
 cm = 1e-02
 e1 = 4.5 * cm; e2 = 6 * cm / 2; e3 =  5 * cm / 2
@@ -21,63 +21,63 @@ def hypot(a, b):
 ccos = (-h5*R1 + e2 * hypot(h5, hypot(e2, R1))) / (h5*h5 + e2*e2)
 ssin = math.sqrt(1 - ccos*ccos)
 
-gmshModelGeoAddPoint(-e1-e2, 0    , 0, Lc1, 1)
-gmshModelGeoAddPoint(-e1-e2, h1   , 0, Lc1, 2)
-gmshModelGeoAddPoint(-e3-r , h1   , 0, Lc2, 3)
-gmshModelGeoAddPoint(-e3-r , h1+r , 0, Lc2, 4)
-gmshModelGeoAddPoint(-e3   , h1+r , 0, Lc2, 5)
-gmshModelGeoAddPoint(-e3   , h1+h2, 0, Lc1, 6)
-gmshModelGeoAddPoint( e3   , h1+h2, 0, Lc1, 7)
-gmshModelGeoAddPoint( e3   , h1+r , 0, Lc2, 8)
-gmshModelGeoAddPoint( e3+r , h1+r , 0, Lc2, 9)
-gmshModelGeoAddPoint( e3+r , h1   , 0, Lc2, 10)
-gmshModelGeoAddPoint( e1+e2, h1   , 0, Lc1, 11)
-gmshModelGeoAddPoint( e1+e2, 0    , 0, Lc1, 12)
-gmshModelGeoAddPoint( e2   , 0    , 0, Lc1, 13)
-
-gmshModelGeoAddPoint( R1 / ssin, h5+R1*ccos, 0, Lc2, 14)
-gmshModelGeoAddPoint( 0        , h5        , 0, Lc2, 15)
-gmshModelGeoAddPoint(-R1 / ssin, h5+R1*ccos, 0, Lc2, 16)
-gmshModelGeoAddPoint(-e2       , 0.0       , 0, Lc1, 17)
-
-gmshModelGeoAddPoint(-R2 , h1+h3   , 0, Lc2, 18)
-gmshModelGeoAddPoint(-R2 , h1+h3+h4, 0, Lc2, 19)
-gmshModelGeoAddPoint( 0  , h1+h3+h4, 0, Lc2, 20)
-gmshModelGeoAddPoint( R2 , h1+h3+h4, 0, Lc2, 21)
-gmshModelGeoAddPoint( R2 , h1+h3   , 0, Lc2, 22)
-gmshModelGeoAddPoint( 0  , h1+h3   , 0, Lc2, 23)
+gmsh.modelGeoAddPoint(-e1-e2, 0    , 0, Lc1, 1)
+gmsh.modelGeoAddPoint(-e1-e2, h1   , 0, Lc1, 2)
+gmsh.modelGeoAddPoint(-e3-r , h1   , 0, Lc2, 3)
+gmsh.modelGeoAddPoint(-e3-r , h1+r , 0, Lc2, 4)
+gmsh.modelGeoAddPoint(-e3   , h1+r , 0, Lc2, 5)
+gmsh.modelGeoAddPoint(-e3   , h1+h2, 0, Lc1, 6)
+gmsh.modelGeoAddPoint( e3   , h1+h2, 0, Lc1, 7)
+gmsh.modelGeoAddPoint( e3   , h1+r , 0, Lc2, 8)
+gmsh.modelGeoAddPoint( e3+r , h1+r , 0, Lc2, 9)
+gmsh.modelGeoAddPoint( e3+r , h1   , 0, Lc2, 10)
+gmsh.modelGeoAddPoint( e1+e2, h1   , 0, Lc1, 11)
+gmsh.modelGeoAddPoint( e1+e2, 0    , 0, Lc1, 12)
+gmsh.modelGeoAddPoint( e2   , 0    , 0, Lc1, 13)
+
+gmsh.modelGeoAddPoint( R1 / ssin, h5+R1*ccos, 0, Lc2, 14)
+gmsh.modelGeoAddPoint( 0        , h5        , 0, Lc2, 15)
+gmsh.modelGeoAddPoint(-R1 / ssin, h5+R1*ccos, 0, Lc2, 16)
+gmsh.modelGeoAddPoint(-e2       , 0.0       , 0, Lc1, 17)
+
+gmsh.modelGeoAddPoint(-R2 , h1+h3   , 0, Lc2, 18)
+gmsh.modelGeoAddPoint(-R2 , h1+h3+h4, 0, Lc2, 19)
+gmsh.modelGeoAddPoint( 0  , h1+h3+h4, 0, Lc2, 20)
+gmsh.modelGeoAddPoint( R2 , h1+h3+h4, 0, Lc2, 21)
+gmsh.modelGeoAddPoint( R2 , h1+h3   , 0, Lc2, 22)
+gmsh.modelGeoAddPoint( 0  , h1+h3   , 0, Lc2, 23)
                                                 
-gmshModelGeoAddPoint( 0, h1+h3+h4+R2, 0, Lc2, 24)
-gmshModelGeoAddPoint( 0, h1+h3-R2,    0, Lc2, 25)
-
-gmshModelGeoAddLine(1 , 17, 1)
-gmshModelGeoAddLine(17, 16, 2)
-
-gmshModelGeoAddCircleArc(14,15,16, 3)
-gmshModelGeoAddLine(14,13, 4)
-gmshModelGeoAddLine(13,12, 5)
-gmshModelGeoAddLine(12,11, 6)
-gmshModelGeoAddLine(11,10, 7)
-gmshModelGeoAddCircleArc(8,9,10, 8)
-gmshModelGeoAddLine(8,7, 9)
-gmshModelGeoAddLine(7,6, 10)
-gmshModelGeoAddLine(6,5, 11)
-gmshModelGeoAddCircleArc(3,4,5, 12)
-gmshModelGeoAddLine(3,2, 13)
-gmshModelGeoAddLine(2,1, 14)
-gmshModelGeoAddLine(18,19, 15)
-gmshModelGeoAddCircleArc(21,20,24, 16)
-gmshModelGeoAddCircleArc(24,20,19, 17)
-gmshModelGeoAddCircleArc(18,23,25, 18)
-gmshModelGeoAddCircleArc(25,23,22, 19)
-gmshModelGeoAddLine(21,22, 20)
-
-gmshModelGeoAddLineLoop([17,-15,18,19,-20,16], 21)
-gmshModelGeoAddPlaneSurface([21], 22)
-gmshModelGeoAddLineLoop([11,-12,13,14,1,2,-3,4,5,6,7,-8,9,10], 23)
+gmsh.modelGeoAddPoint( 0, h1+h3+h4+R2, 0, Lc2, 24)
+gmsh.modelGeoAddPoint( 0, h1+h3-R2,    0, Lc2, 25)
+
+gmsh.modelGeoAddLine(1 , 17, 1)
+gmsh.modelGeoAddLine(17, 16, 2)
+
+gmsh.modelGeoAddCircleArc(14,15,16, 3)
+gmsh.modelGeoAddLine(14,13, 4)
+gmsh.modelGeoAddLine(13,12, 5)
+gmsh.modelGeoAddLine(12,11, 6)
+gmsh.modelGeoAddLine(11,10, 7)
+gmsh.modelGeoAddCircleArc(8,9,10, 8)
+gmsh.modelGeoAddLine(8,7, 9)
+gmsh.modelGeoAddLine(7,6, 10)
+gmsh.modelGeoAddLine(6,5, 11)
+gmsh.modelGeoAddCircleArc(3,4,5, 12)
+gmsh.modelGeoAddLine(3,2, 13)
+gmsh.modelGeoAddLine(2,1, 14)
+gmsh.modelGeoAddLine(18,19, 15)
+gmsh.modelGeoAddCircleArc(21,20,24, 16)
+gmsh.modelGeoAddCircleArc(24,20,19, 17)
+gmsh.modelGeoAddCircleArc(18,23,25, 18)
+gmsh.modelGeoAddCircleArc(25,23,22, 19)
+gmsh.modelGeoAddLine(21,22, 20)
+
+gmsh.modelGeoAddLineLoop([17,-15,18,19,-20,16], 21)
+gmsh.modelGeoAddPlaneSurface([21], 22)
+gmsh.modelGeoAddLineLoop([11,-12,13,14,1,2,-3,4,5,6,7,-8,9,10], 23)
 
 # A surface with one hole is specified using 2 line loops:
-gmshModelGeoAddPlaneSurface([23,21], 24)
+gmsh.modelGeoAddPlaneSurface([23,21], 24)
 
 # FIXME: this will be implemented through the gmshView API
 #  View "comments" {
@@ -89,10 +89,10 @@ gmshModelGeoAddPlaneSurface([23,21], 24)
 #    T2(350, -7, 0){ "file://image.png@20x0" };
 # };
 
-gmshModelGeoSynchronize()
+gmsh.modelGeoSynchronize()
 
-gmshModelMesh(2)
+gmsh.modelMeshGenerate(2)
 
-gmshExport("t4.msh")
+gmsh.write("t4.msh")
 
-gmshFinalize()
+gmsh.finalize()
diff --git a/demos/api/t5.cpp b/demos/api/t5.cpp
index fb07865d46f3b51cfba05c624158b52b6bcef8b7..3b8110e634978f8e1c196b85a13cb9d6b3aa1524 100644
--- a/demos/api/t5.cpp
+++ b/demos/api/t5.cpp
@@ -3,123 +3,125 @@
 #include <gmsh.h>
 #include <cstdio>
 
+using namespace gmsh;
+
 void cheeseHole(double x, double y, double z, double r, double lc,
                 std::vector<int> &shells, std::vector<int> &volumes)
 {
   // When the tag is not specified, a new one is automatically provided
-  int p1 = gmshModelGeoAddPoint(x,  y,  z,  lc);
-  int p2 = gmshModelGeoAddPoint(x+r,y,  z,   lc);
-  int p3 = gmshModelGeoAddPoint(x,  y+r,z,   lc);
-  int p4 = gmshModelGeoAddPoint(x,  y,  z+r, lc);
-  int p5 = gmshModelGeoAddPoint(x-r,y,  z,   lc);
-  int p6 = gmshModelGeoAddPoint(x,  y-r,z,   lc);
-  int p7 = gmshModelGeoAddPoint(x,  y,  z-r, lc);
-
-  int c1 = gmshModelGeoAddCircleArc(p2,p1,p7);
-  int c2 = gmshModelGeoAddCircleArc(p7,p1,p5);
-  int c3 = gmshModelGeoAddCircleArc(p5,p1,p4);
-  int c4 = gmshModelGeoAddCircleArc(p4,p1,p2);
-  int c5 = gmshModelGeoAddCircleArc(p2,p1,p3);
-  int c6 = gmshModelGeoAddCircleArc(p3,p1,p5);
-  int c7 = gmshModelGeoAddCircleArc(p5,p1,p6);
-  int c8 = gmshModelGeoAddCircleArc(p6,p1,p2);
-  int c9 = gmshModelGeoAddCircleArc(p7,p1,p3);
-  int c10 = gmshModelGeoAddCircleArc(p3,p1,p4);
-  int c11 = gmshModelGeoAddCircleArc(p4,p1,p6);
-  int c12 = gmshModelGeoAddCircleArc(p6,p1,p7);
-
-  int l1 = gmshModelGeoAddLineLoop({c5,c10,c4});
-  int l2 = gmshModelGeoAddLineLoop({c9,-c5,c1});
-  int l3 = gmshModelGeoAddLineLoop({c12,-c8,-c1});
-  int l4 = gmshModelGeoAddLineLoop({c8,-c4,c11});
-  int l5 = gmshModelGeoAddLineLoop({-c10,c6,c3});
-  int l6 = gmshModelGeoAddLineLoop({-c11,-c3,c7});
-  int l7 = gmshModelGeoAddLineLoop({-c2,-c7,-c12});
-  int l8 = gmshModelGeoAddLineLoop({-c6,-c9,c2});
-
-  int s1 = gmshModelGeoAddSurfaceFilling({l1});
-  int s2 = gmshModelGeoAddSurfaceFilling({l2});
-  int s3 = gmshModelGeoAddSurfaceFilling({l3});
-  int s4 = gmshModelGeoAddSurfaceFilling({l4});
-  int s5 = gmshModelGeoAddSurfaceFilling({l5});
-  int s6 = gmshModelGeoAddSurfaceFilling({l6});
-  int s7 = gmshModelGeoAddSurfaceFilling({l7});
-  int s8 = gmshModelGeoAddSurfaceFilling({l8});
-
-  int sl = gmshModelGeoAddSurfaceLoop({s1, s2, s3, s4, s5, s6, s7, s8});
-  int v = gmshModelGeoAddVolume({sl});
+  int p1 = model::geo::addPoint(x,  y,  z,  lc);
+  int p2 = model::geo::addPoint(x+r,y,  z,   lc);
+  int p3 = model::geo::addPoint(x,  y+r,z,   lc);
+  int p4 = model::geo::addPoint(x,  y,  z+r, lc);
+  int p5 = model::geo::addPoint(x-r,y,  z,   lc);
+  int p6 = model::geo::addPoint(x,  y-r,z,   lc);
+  int p7 = model::geo::addPoint(x,  y,  z-r, lc);
+
+  int c1 = model::geo::addCircleArc(p2,p1,p7);
+  int c2 = model::geo::addCircleArc(p7,p1,p5);
+  int c3 = model::geo::addCircleArc(p5,p1,p4);
+  int c4 = model::geo::addCircleArc(p4,p1,p2);
+  int c5 = model::geo::addCircleArc(p2,p1,p3);
+  int c6 = model::geo::addCircleArc(p3,p1,p5);
+  int c7 = model::geo::addCircleArc(p5,p1,p6);
+  int c8 = model::geo::addCircleArc(p6,p1,p2);
+  int c9 = model::geo::addCircleArc(p7,p1,p3);
+  int c10 = model::geo::addCircleArc(p3,p1,p4);
+  int c11 = model::geo::addCircleArc(p4,p1,p6);
+  int c12 = model::geo::addCircleArc(p6,p1,p7);
+
+  int l1 = model::geo::addLineLoop({c5,c10,c4});
+  int l2 = model::geo::addLineLoop({c9,-c5,c1});
+  int l3 = model::geo::addLineLoop({c12,-c8,-c1});
+  int l4 = model::geo::addLineLoop({c8,-c4,c11});
+  int l5 = model::geo::addLineLoop({-c10,c6,c3});
+  int l6 = model::geo::addLineLoop({-c11,-c3,c7});
+  int l7 = model::geo::addLineLoop({-c2,-c7,-c12});
+  int l8 = model::geo::addLineLoop({-c6,-c9,c2});
+
+  int s1 = model::geo::addSurfaceFilling({l1});
+  int s2 = model::geo::addSurfaceFilling({l2});
+  int s3 = model::geo::addSurfaceFilling({l3});
+  int s4 = model::geo::addSurfaceFilling({l4});
+  int s5 = model::geo::addSurfaceFilling({l5});
+  int s6 = model::geo::addSurfaceFilling({l6});
+  int s7 = model::geo::addSurfaceFilling({l7});
+  int s8 = model::geo::addSurfaceFilling({l8});
+
+  int sl = model::geo::addSurfaceLoop({s1, s2, s3, s4, s5, s6, s7, s8});
+  int v = model::geo::addVolume({sl});
   shells.push_back(sl);
   volumes.push_back(v);
 }
 
 int main(int argc, char **argv)
 {
-  gmshInitialize();
-  gmshOptionSetNumber("General.Terminal", 1);
+  initialize();
+  option::setNumber("General.Terminal", 1);
 
   double lcar1 = .1;
   double lcar2 = .0005;
   double lcar3 = .055;
 
-  gmshModelGeoAddPoint(0.5,0.5,0.5, lcar2, 1);
-  gmshModelGeoAddPoint(0.5,0.5,0, lcar1, 2);
-  gmshModelGeoAddPoint(0,0.5,0.5, lcar1, 3);
-  gmshModelGeoAddPoint(0,0,0.5, lcar1, 4);
-  gmshModelGeoAddPoint(0.5,0,0.5, lcar1, 5);
-  gmshModelGeoAddPoint(0.5,0,0, lcar1, 6);
-  gmshModelGeoAddPoint(0,0.5,0, lcar1, 7);
-  gmshModelGeoAddPoint(0,1,0, lcar1, 8);
-  gmshModelGeoAddPoint(1,1,0, lcar1, 9);
-  gmshModelGeoAddPoint(0,0,1, lcar1, 10);
-  gmshModelGeoAddPoint(0,1,1, lcar1, 11);
-  gmshModelGeoAddPoint(1,1,1, lcar1, 12);
-  gmshModelGeoAddPoint(1,0,1, lcar1, 13);
-  gmshModelGeoAddPoint(1,0,0, lcar1, 14);
-
-  gmshModelGeoAddLine(8,9, 1);
-  gmshModelGeoAddLine(9,12, 2);
-  gmshModelGeoAddLine(12,11, 3);
-  gmshModelGeoAddLine(11,8, 4);
-  gmshModelGeoAddLine(9,14, 5);
-  gmshModelGeoAddLine(14,13, 6);
-  gmshModelGeoAddLine(13,12, 7);
-  gmshModelGeoAddLine(11,10, 8);
-  gmshModelGeoAddLine(10,13, 9);
-  gmshModelGeoAddLine(10,4, 10);
-  gmshModelGeoAddLine(4,5, 11);
-  gmshModelGeoAddLine(5,6, 12);
-  gmshModelGeoAddLine(6,2, 13);
-  gmshModelGeoAddLine(2,1, 14);
-  gmshModelGeoAddLine(1,3, 15);
-  gmshModelGeoAddLine(3,7, 16);
-  gmshModelGeoAddLine(7,2, 17);
-  gmshModelGeoAddLine(3,4, 18);
-  gmshModelGeoAddLine(5,1, 19);
-  gmshModelGeoAddLine(7,8, 20);
-  gmshModelGeoAddLine(6,14, 21);
-
-  gmshModelGeoAddLineLoop({-11,-19,-15,-18}, 22);
-  gmshModelGeoAddPlaneSurface({22}, 23);
-  gmshModelGeoAddLineLoop({16,17,14,15}, 24);
-  gmshModelGeoAddPlaneSurface({24}, 25);
-  gmshModelGeoAddLineLoop({-17,20,1,5,-21,13}, 26);
-  gmshModelGeoAddPlaneSurface({26}, 27);
-  gmshModelGeoAddLineLoop({-4,-1,-2,-3}, 28);
-  gmshModelGeoAddPlaneSurface({28}, 29);
-  gmshModelGeoAddLineLoop({-7,2,-5,-6}, 30);
-  gmshModelGeoAddPlaneSurface({30}, 31);
-  gmshModelGeoAddLineLoop({6,-9,10,11,12,21}, 32);
-  gmshModelGeoAddPlaneSurface({32}, 33);
-  gmshModelGeoAddLineLoop({7,3,8,9}, 34);
-  gmshModelGeoAddPlaneSurface({34}, 35);
-  gmshModelGeoAddLineLoop({-10,18,-16,-20,4,-8}, 36);
-  gmshModelGeoAddPlaneSurface({36}, 37);
-  gmshModelGeoAddLineLoop({-14,-13,-12,19}, 38);
-  gmshModelGeoAddPlaneSurface({38}, 39);
+  model::geo::addPoint(0.5,0.5,0.5, lcar2, 1);
+  model::geo::addPoint(0.5,0.5,0, lcar1, 2);
+  model::geo::addPoint(0,0.5,0.5, lcar1, 3);
+  model::geo::addPoint(0,0,0.5, lcar1, 4);
+  model::geo::addPoint(0.5,0,0.5, lcar1, 5);
+  model::geo::addPoint(0.5,0,0, lcar1, 6);
+  model::geo::addPoint(0,0.5,0, lcar1, 7);
+  model::geo::addPoint(0,1,0, lcar1, 8);
+  model::geo::addPoint(1,1,0, lcar1, 9);
+  model::geo::addPoint(0,0,1, lcar1, 10);
+  model::geo::addPoint(0,1,1, lcar1, 11);
+  model::geo::addPoint(1,1,1, lcar1, 12);
+  model::geo::addPoint(1,0,1, lcar1, 13);
+  model::geo::addPoint(1,0,0, lcar1, 14);
+
+  model::geo::addLine(8,9, 1);
+  model::geo::addLine(9,12, 2);
+  model::geo::addLine(12,11, 3);
+  model::geo::addLine(11,8, 4);
+  model::geo::addLine(9,14, 5);
+  model::geo::addLine(14,13, 6);
+  model::geo::addLine(13,12, 7);
+  model::geo::addLine(11,10, 8);
+  model::geo::addLine(10,13, 9);
+  model::geo::addLine(10,4, 10);
+  model::geo::addLine(4,5, 11);
+  model::geo::addLine(5,6, 12);
+  model::geo::addLine(6,2, 13);
+  model::geo::addLine(2,1, 14);
+  model::geo::addLine(1,3, 15);
+  model::geo::addLine(3,7, 16);
+  model::geo::addLine(7,2, 17);
+  model::geo::addLine(3,4, 18);
+  model::geo::addLine(5,1, 19);
+  model::geo::addLine(7,8, 20);
+  model::geo::addLine(6,14, 21);
+
+  model::geo::addLineLoop({-11,-19,-15,-18}, 22);
+  model::geo::addPlaneSurface({22}, 23);
+  model::geo::addLineLoop({16,17,14,15}, 24);
+  model::geo::addPlaneSurface({24}, 25);
+  model::geo::addLineLoop({-17,20,1,5,-21,13}, 26);
+  model::geo::addPlaneSurface({26}, 27);
+  model::geo::addLineLoop({-4,-1,-2,-3}, 28);
+  model::geo::addPlaneSurface({28}, 29);
+  model::geo::addLineLoop({-7,2,-5,-6}, 30);
+  model::geo::addPlaneSurface({30}, 31);
+  model::geo::addLineLoop({6,-9,10,11,12,21}, 32);
+  model::geo::addPlaneSurface({32}, 33);
+  model::geo::addLineLoop({7,3,8,9}, 34);
+  model::geo::addPlaneSurface({34}, 35);
+  model::geo::addLineLoop({-10,18,-16,-20,4,-8}, 36);
+  model::geo::addPlaneSurface({36}, 37);
+  model::geo::addLineLoop({-14,-13,-12,19}, 38);
+  model::geo::addPlaneSurface({38}, 39);
 
   std::vector<int> shells, volumes;
 
-  int sl = gmshModelGeoAddSurfaceLoop({35,31,29,37,33,23,39,25,27});
+  int sl = model::geo::addSurfaceLoop({35,31,29,37,33,23,39,25,27});
   shells.push_back(sl);
 
   double x = 0, y = 0.75, z = 0, r = 0.09 ;
@@ -127,16 +129,16 @@ int main(int argc, char **argv)
     x += 0.166 ;
     z += 0.166 ;
     cheeseHole(x, y, z, r, lcar3, shells, volumes);
-    gmshModelAddPhysicalGroup(3, {volumes.back()}, t);
+    model::addPhysicalGroup(3, {volumes.back()}, t);
     std::printf("Hole %d (center = {%g,%g,%g}, radius = %g) has number %d!\n",
                 t, x, y, z, r, volumes.back());
   }
 
-  gmshModelGeoAddVolume(shells, 186);
+  model::geo::addVolume(shells, 186);
 
-  gmshModelAddPhysicalGroup(3, {186}, 10);
-  gmshModelGeoSynchronize();
-  gmshModelMesh(3);
-  gmshExport("t5.msh");
+  model::addPhysicalGroup(3, {186}, 10);
+  model::geo::synchronize();
+  model::mesh::generate(3);
+  write("t5.msh");
   return 0;
 }
diff --git a/demos/api/t5.py b/demos/api/t5.py
index 9f1a3e7039d36b6168c91d47f356febb997832e9..7bf3f52165aefe0e091ac6d4cb1ba19ef2e463d9 100644
--- a/demos/api/t5.py
+++ b/demos/api/t5.py
@@ -1,111 +1,111 @@
 # This file reimplements gmsh/tutorial/t5.geo in Python.
 
-from gmsh import *
+import gmsh
 import math
 
-gmshInitialize()
-gmshOptionSetNumber("General.Terminal", 1)
+gmsh.initialize()
+gmsh.optionSetNumber("General.Terminal", 1)
 
-gmshModelCreate("t5")
+gmsh.modelAdd("t5")
 
 lcar1 = .1
 lcar2 = .0005
 lcar3 = .055
 
-gmshModelGeoAddPoint(0.5,0.5,0.5, lcar2, 1)
-gmshModelGeoAddPoint(0.5,0.5,0, lcar1, 2)
-gmshModelGeoAddPoint(0,0.5,0.5, lcar1, 3)
-gmshModelGeoAddPoint(0,0,0.5, lcar1, 4)
-gmshModelGeoAddPoint(0.5,0,0.5, lcar1, 5)
-gmshModelGeoAddPoint(0.5,0,0, lcar1, 6)
-gmshModelGeoAddPoint(0,0.5,0, lcar1, 7)
-gmshModelGeoAddPoint(0,1,0, lcar1, 8)
-gmshModelGeoAddPoint(1,1,0, lcar1, 9)
-gmshModelGeoAddPoint(0,0,1, lcar1, 10)
-gmshModelGeoAddPoint(0,1,1, lcar1, 11)
-gmshModelGeoAddPoint(1,1,1, lcar1, 12)
-gmshModelGeoAddPoint(1,0,1, lcar1, 13)
-gmshModelGeoAddPoint(1,0,0, lcar1, 14)
+gmsh.modelGeoAddPoint(0.5,0.5,0.5, lcar2, 1)
+gmsh.modelGeoAddPoint(0.5,0.5,0, lcar1, 2)
+gmsh.modelGeoAddPoint(0,0.5,0.5, lcar1, 3)
+gmsh.modelGeoAddPoint(0,0,0.5, lcar1, 4)
+gmsh.modelGeoAddPoint(0.5,0,0.5, lcar1, 5)
+gmsh.modelGeoAddPoint(0.5,0,0, lcar1, 6)
+gmsh.modelGeoAddPoint(0,0.5,0, lcar1, 7)
+gmsh.modelGeoAddPoint(0,1,0, lcar1, 8)
+gmsh.modelGeoAddPoint(1,1,0, lcar1, 9)
+gmsh.modelGeoAddPoint(0,0,1, lcar1, 10)
+gmsh.modelGeoAddPoint(0,1,1, lcar1, 11)
+gmsh.modelGeoAddPoint(1,1,1, lcar1, 12)
+gmsh.modelGeoAddPoint(1,0,1, lcar1, 13)
+gmsh.modelGeoAddPoint(1,0,0, lcar1, 14)
 
-gmshModelGeoAddLine(8,9, 1);   gmshModelGeoAddLine(9,12, 2)
-gmshModelGeoAddLine(12,11, 3); gmshModelGeoAddLine(11,8, 4)
-gmshModelGeoAddLine(9,14, 5);  gmshModelGeoAddLine(14,13, 6)
-gmshModelGeoAddLine(13,12, 7); gmshModelGeoAddLine(11,10, 8)
-gmshModelGeoAddLine(10,13, 9); gmshModelGeoAddLine(10,4, 10)
-gmshModelGeoAddLine(4,5, 11);  gmshModelGeoAddLine(5,6, 12)
-gmshModelGeoAddLine(6,2, 13);  gmshModelGeoAddLine(2,1, 14)
-gmshModelGeoAddLine(1,3, 15);  gmshModelGeoAddLine(3,7, 16)
-gmshModelGeoAddLine(7,2, 17);  gmshModelGeoAddLine(3,4, 18)
-gmshModelGeoAddLine(5,1, 19);  gmshModelGeoAddLine(7,8, 20)
-gmshModelGeoAddLine(6,14, 21); 
+gmsh.modelGeoAddLine(8,9, 1);   gmsh.modelGeoAddLine(9,12, 2)
+gmsh.modelGeoAddLine(12,11, 3); gmsh.modelGeoAddLine(11,8, 4)
+gmsh.modelGeoAddLine(9,14, 5);  gmsh.modelGeoAddLine(14,13, 6)
+gmsh.modelGeoAddLine(13,12, 7); gmsh.modelGeoAddLine(11,10, 8)
+gmsh.modelGeoAddLine(10,13, 9); gmsh.modelGeoAddLine(10,4, 10)
+gmsh.modelGeoAddLine(4,5, 11);  gmsh.modelGeoAddLine(5,6, 12)
+gmsh.modelGeoAddLine(6,2, 13);  gmsh.modelGeoAddLine(2,1, 14)
+gmsh.modelGeoAddLine(1,3, 15);  gmsh.modelGeoAddLine(3,7, 16)
+gmsh.modelGeoAddLine(7,2, 17);  gmsh.modelGeoAddLine(3,4, 18)
+gmsh.modelGeoAddLine(5,1, 19);  gmsh.modelGeoAddLine(7,8, 20)
+gmsh.modelGeoAddLine(6,14, 21); 
 
-gmshModelGeoAddLineLoop([-11,-19,-15,-18], 22)
-gmshModelGeoAddPlaneSurface([22], 23)
-gmshModelGeoAddLineLoop([16,17,14,15], 24)
-gmshModelGeoAddPlaneSurface([24], 25)
-gmshModelGeoAddLineLoop([-17,20,1,5,-21,13], 26)
-gmshModelGeoAddPlaneSurface([26], 27)
-gmshModelGeoAddLineLoop([-4,-1,-2,-3], 28)
-gmshModelGeoAddPlaneSurface([28], 29)
-gmshModelGeoAddLineLoop([-7,2,-5,-6], 30)
-gmshModelGeoAddPlaneSurface([30], 31)
-gmshModelGeoAddLineLoop([6,-9,10,11,12,21], 32)
-gmshModelGeoAddPlaneSurface([32], 33)
-gmshModelGeoAddLineLoop([7,3,8,9], 34)
-gmshModelGeoAddPlaneSurface([34], 35)
-gmshModelGeoAddLineLoop([-10,18,-16,-20,4,-8], 36)
-gmshModelGeoAddPlaneSurface([36], 37)
-gmshModelGeoAddLineLoop([-14,-13,-12,19], 38)
-gmshModelGeoAddPlaneSurface([38], 39)
+gmsh.modelGeoAddLineLoop([-11,-19,-15,-18], 22)
+gmsh.modelGeoAddPlaneSurface([22], 23)
+gmsh.modelGeoAddLineLoop([16,17,14,15], 24)
+gmsh.modelGeoAddPlaneSurface([24], 25)
+gmsh.modelGeoAddLineLoop([-17,20,1,5,-21,13], 26)
+gmsh.modelGeoAddPlaneSurface([26], 27)
+gmsh.modelGeoAddLineLoop([-4,-1,-2,-3], 28)
+gmsh.modelGeoAddPlaneSurface([28], 29)
+gmsh.modelGeoAddLineLoop([-7,2,-5,-6], 30)
+gmsh.modelGeoAddPlaneSurface([30], 31)
+gmsh.modelGeoAddLineLoop([6,-9,10,11,12,21], 32)
+gmsh.modelGeoAddPlaneSurface([32], 33)
+gmsh.modelGeoAddLineLoop([7,3,8,9], 34)
+gmsh.modelGeoAddPlaneSurface([34], 35)
+gmsh.modelGeoAddLineLoop([-10,18,-16,-20,4,-8], 36)
+gmsh.modelGeoAddPlaneSurface([36], 37)
+gmsh.modelGeoAddLineLoop([-14,-13,-12,19], 38)
+gmsh.modelGeoAddPlaneSurface([38], 39)
 
-shells = IntVector(); volumes = IntVector()
+shells = gmsh.IntVector(); volumes = gmsh.IntVector()
 
 # When the tag is not specified, a new one is automatically provided
-sl = gmshModelGeoAddSurfaceLoop([35,31,29,37,33,23,39,25,27])
+sl = gmsh.modelGeoAddSurfaceLoop([35,31,29,37,33,23,39,25,27])
 shells.push_back(sl)
 
 def cheeseHole(x, y, z, r, lc, shells, volumes):
-    p1 = gmshModelGeoAddPoint(x,  y,  z,   lc)
-    p2 = gmshModelGeoAddPoint(x+r,y,  z,   lc)
-    p3 = gmshModelGeoAddPoint(x,  y+r,z,   lc)
-    p4 = gmshModelGeoAddPoint(x,  y,  z+r, lc)
-    p5 = gmshModelGeoAddPoint(x-r,y,  z,   lc)
-    p6 = gmshModelGeoAddPoint(x,  y-r,z,   lc)
-    p7 = gmshModelGeoAddPoint(x,  y,  z-r, lc)
+    p1 = gmsh.modelGeoAddPoint(x,  y,  z,   lc)
+    p2 = gmsh.modelGeoAddPoint(x+r,y,  z,   lc)
+    p3 = gmsh.modelGeoAddPoint(x,  y+r,z,   lc)
+    p4 = gmsh.modelGeoAddPoint(x,  y,  z+r, lc)
+    p5 = gmsh.modelGeoAddPoint(x-r,y,  z,   lc)
+    p6 = gmsh.modelGeoAddPoint(x,  y-r,z,   lc)
+    p7 = gmsh.modelGeoAddPoint(x,  y,  z-r, lc)
 
-    c1 = gmshModelGeoAddCircleArc(p2,p1,p7)
-    c2 = gmshModelGeoAddCircleArc(p7,p1,p5)
-    c3 = gmshModelGeoAddCircleArc(p5,p1,p4)
-    c4 = gmshModelGeoAddCircleArc(p4,p1,p2)
-    c5 = gmshModelGeoAddCircleArc(p2,p1,p3)
-    c6 = gmshModelGeoAddCircleArc(p3,p1,p5)
-    c7 = gmshModelGeoAddCircleArc(p5,p1,p6)
-    c8 = gmshModelGeoAddCircleArc(p6,p1,p2)
-    c9 = gmshModelGeoAddCircleArc(p7,p1,p3)
-    c10 = gmshModelGeoAddCircleArc(p3,p1,p4)
-    c11 = gmshModelGeoAddCircleArc(p4,p1,p6)
-    c12 = gmshModelGeoAddCircleArc(p6,p1,p7)
+    c1 = gmsh.modelGeoAddCircleArc(p2,p1,p7)
+    c2 = gmsh.modelGeoAddCircleArc(p7,p1,p5)
+    c3 = gmsh.modelGeoAddCircleArc(p5,p1,p4)
+    c4 = gmsh.modelGeoAddCircleArc(p4,p1,p2)
+    c5 = gmsh.modelGeoAddCircleArc(p2,p1,p3)
+    c6 = gmsh.modelGeoAddCircleArc(p3,p1,p5)
+    c7 = gmsh.modelGeoAddCircleArc(p5,p1,p6)
+    c8 = gmsh.modelGeoAddCircleArc(p6,p1,p2)
+    c9 = gmsh.modelGeoAddCircleArc(p7,p1,p3)
+    c10 = gmsh.modelGeoAddCircleArc(p3,p1,p4)
+    c11 = gmsh.modelGeoAddCircleArc(p4,p1,p6)
+    c12 = gmsh.modelGeoAddCircleArc(p6,p1,p7)
     
-    l1 = gmshModelGeoAddLineLoop([c5,c10,c4])
-    l2 = gmshModelGeoAddLineLoop([c9,-c5,c1])
-    l3 = gmshModelGeoAddLineLoop([c12,-c8,-c1])
-    l4 = gmshModelGeoAddLineLoop([c8,-c4,c11])
-    l5 = gmshModelGeoAddLineLoop([-c10,c6,c3])
-    l6 = gmshModelGeoAddLineLoop([-c11,-c3,c7])
-    l7 = gmshModelGeoAddLineLoop([-c2,-c7,-c12])
-    l8 = gmshModelGeoAddLineLoop([-c6,-c9,c2])
+    l1 = gmsh.modelGeoAddLineLoop([c5,c10,c4])
+    l2 = gmsh.modelGeoAddLineLoop([c9,-c5,c1])
+    l3 = gmsh.modelGeoAddLineLoop([c12,-c8,-c1])
+    l4 = gmsh.modelGeoAddLineLoop([c8,-c4,c11])
+    l5 = gmsh.modelGeoAddLineLoop([-c10,c6,c3])
+    l6 = gmsh.modelGeoAddLineLoop([-c11,-c3,c7])
+    l7 = gmsh.modelGeoAddLineLoop([-c2,-c7,-c12])
+    l8 = gmsh.modelGeoAddLineLoop([-c6,-c9,c2])
     
-    s1 = gmshModelGeoAddSurfaceFilling([l1])
-    s2 = gmshModelGeoAddSurfaceFilling([l2])
-    s3 = gmshModelGeoAddSurfaceFilling([l3])
-    s4 = gmshModelGeoAddSurfaceFilling([l4])
-    s5 = gmshModelGeoAddSurfaceFilling([l5])
-    s6 = gmshModelGeoAddSurfaceFilling([l6])
-    s7 = gmshModelGeoAddSurfaceFilling([l7])
-    s8 = gmshModelGeoAddSurfaceFilling([l8])
+    s1 = gmsh.modelGeoAddSurfaceFilling([l1])
+    s2 = gmsh.modelGeoAddSurfaceFilling([l2])
+    s3 = gmsh.modelGeoAddSurfaceFilling([l3])
+    s4 = gmsh.modelGeoAddSurfaceFilling([l4])
+    s5 = gmsh.modelGeoAddSurfaceFilling([l5])
+    s6 = gmsh.modelGeoAddSurfaceFilling([l6])
+    s7 = gmsh.modelGeoAddSurfaceFilling([l7])
+    s8 = gmsh.modelGeoAddSurfaceFilling([l8])
     
-    sl = gmshModelGeoAddSurfaceLoop([s1, s2, s3, s4, s5, s6, s7, s8])
-    v = gmshModelGeoAddVolume([sl])
+    sl = gmsh.modelGeoAddSurfaceLoop([s1, s2, s3, s4, s5, s6, s7, s8])
+    v = gmsh.modelGeoAddVolume([sl])
     shells.append(sl)
     volumes.append(v)
 
@@ -114,13 +114,13 @@ for t in range(1, 6):
     x += 0.166 ;
     z += 0.166 ;
     cheeseHole(x, y, z, r, lcar3, shells, volumes);
-    gmshModelAddPhysicalGroup(3, [volumes.back()], t);
+    gmsh.modelAddPhysicalGroup(3, [volumes.back()], t);
 
-gmshModelGeoAddVolume(shells, 186);
+gmsh.modelGeoAddVolume(shells, 186);
       
-gmshModelAddPhysicalGroup(3, [186], 10);
-gmshModelGeoSynchronize()
-gmshModelMesh(3)
-gmshExport("t5.msh")
+gmsh.modelAddPhysicalGroup(3, [186], 10);
+gmsh.modelGeoSynchronize()
+gmsh.modelMeshGenerate(3)
+gmsh.write("t5.msh")
 
-gmshFinalize()
+gmsh.finalize()
diff --git a/demos/api/t6.cpp b/demos/api/t6.cpp
index 579d6997eb77b3d8452d2009d37e98daeb9af3eb..9f9f846da50416acca5974bc88ad89c70e00aca5 100644
--- a/demos/api/t6.cpp
+++ b/demos/api/t6.cpp
@@ -2,92 +2,95 @@
 
 #include <gmsh.h>
 
+using namespace gmsh;
+
 int main(int argc, char **argv)
 {
-  gmshInitialize();
-  gmshOptionSetNumber("General.Terminal", 1);
-
-  gmshModelCreate("t2");
+  initialize();
+  option::setNumber("General.Terminal", 1);
 
+  model::add("t2");
 
   // Copied from t1.cpp...
   double lc = 1e-2;
-  gmshModelGeoAddPoint(0, 0, 0, lc, 1);
-  gmshModelGeoAddPoint(.1, 0,  0, lc, 2);
-  gmshModelGeoAddPoint(.1, .3, 0, lc, 3);
-  gmshModelGeoAddPoint(0,  .3, 0, lc, 4);
-  gmshModelGeoAddLine(1, 2, 1);
-  gmshModelGeoAddLine(3, 2, 2);
-  gmshModelGeoAddLine(3, 4, 3);
-  gmshModelGeoAddLine(4, 1, 4);
-  gmshModelGeoAddLineLoop({4, 1, -2, 3}, 1);
-  gmshModelGeoAddPlaneSurface({1}, 1);
-  gmshModelAddPhysicalGroup(0, {1, 2}, 1);
-  gmshModelAddPhysicalGroup(1, {1, 2}, 2);
-  gmshModelAddPhysicalGroup(2, {1}, 6);
-  gmshModelSetPhysicalName(2, 6, "My surface");
+  model::geo::addPoint(0, 0, 0, lc, 1);
+  model::geo::addPoint(.1, 0,  0, lc, 2);
+  model::geo::addPoint(.1, .3, 0, lc, 3);
+  model::geo::addPoint(0,  .3, 0, lc, 4);
+  model::geo::addLine(1, 2, 1);
+  model::geo::addLine(3, 2, 2);
+  model::geo::addLine(3, 4, 3);
+  model::geo::addLine(4, 1, 4);
+  model::geo::addLineLoop({4, 1, -2, 3}, 1);
+  model::geo::addPlaneSurface({1}, 1);
+  model::addPhysicalGroup(0, {1, 2}, 1);
+  model::addPhysicalGroup(1, {1, 2}, 2);
+  model::addPhysicalGroup(2, {1}, 6);
+  model::setPhysicalName(2, 6, "My surface");
   // ...end of copy
 
   // Delete surface 1 and left boundary (line 4)
-  gmshModelGeoRemove({{2,1}, {1,4}});
+  model::geo::remove({{2,1}, {1,4}});
 
   // Replace left boundary with 3 new lines
-  int p1 = gmshModelGeoAddPoint(-0.05, 0.05, 0, lc);
-  int p2 = gmshModelGeoAddPoint(-0.05, 0.1, 0, lc);
-  int l1 = gmshModelGeoAddLine(1, p1);
-  int l2 = gmshModelGeoAddLine(p1, p2);
-  int l3 = gmshModelGeoAddLine(p2, 4);
+  int p1 = model::geo::addPoint(-0.05, 0.05, 0, lc);
+  int p2 = model::geo::addPoint(-0.05, 0.1, 0, lc);
+  int l1 = model::geo::addLine(1, p1);
+  int l2 = model::geo::addLine(p1, p2);
+  int l3 = model::geo::addLine(p2, 4);
 
   // Recreate surface
-  gmshModelGeoAddLineLoop({2, -1, l1, l2, l3, -3}, 2);
-  gmshModelGeoAddPlaneSurface({-2}, 1);
+  model::geo::addLineLoop({2, -1, l1, l2, l3, -3}, 2);
+  model::geo::addPlaneSurface({-2}, 1);
 
   // Put 20 points with a refinement toward the extremities on curve 2
-  gmshModelGeoSetTransfiniteLine(2, 20, "Bump", 0.05);
+  model::geo::mesh::setTransfiniteLine(2, 20, "Bump", 0.05);
 
   // Put 20 points total on combination of curves l1, l2 and l3 (beware that the
   // points p1 and p2 are shared by the curves, so we do not create 6 + 6 + 10 =
   // 22 points, but 20!)
-  gmshModelGeoSetTransfiniteLine(l1, 6);
-  gmshModelGeoSetTransfiniteLine(l2, 6);
-  gmshModelGeoSetTransfiniteLine(l3, 10);
+  model::geo::mesh::setTransfiniteLine(l1, 6);
+  model::geo::mesh::setTransfiniteLine(l2, 6);
+  model::geo::mesh::setTransfiniteLine(l3, 10);
 
   // Put 30 points following a geometric progression on curve 1 (reversed) and
   // on curve 3
-  gmshModelGeoSetTransfiniteLine(1, 30, "Progression", -1.2);
-  gmshModelGeoSetTransfiniteLine(3, 30, "Progression", 1.2);
+  model::geo::mesh::setTransfiniteLine(1, 30, "Progression", -1.2);
+  model::geo::mesh::setTransfiniteLine(3, 30, "Progression", 1.2);
 
   // Define the Surface as transfinite, by specifying the four corners of the
   // transfinite interpolation
-  gmshModelGeoSetTransfiniteSurface(1, "Left", {1,2,3,4});
+  model::geo::mesh::setTransfiniteSurface(1, "Left", {1,2,3,4});
 
   // Recombine the triangles into quads
-  gmshModelGeoSetRecombine(2, 1);
+  model::geo::mesh::setRecombine(2, 1);
 
   // Apply an elliptic smoother to the grid
-  gmshOptionSetNumber("Mesh.Smoothing", 100);
-  gmshModelAddPhysicalGroup(2, {1}, 1);
+  option::setNumber("Mesh.Smoothing", 100);
+  model::addPhysicalGroup(2, {1}, 1);
 
   // When the surface has only 3 or 4 control points, the transfinite constraint
   // can be applied automatically (without specifying the corners explictly).
-  gmshModelGeoAddPoint(0.2, 0.2, 0, 1.0, 7);
-  gmshModelGeoAddPoint(0.2, 0.1, 0, 1.0, 8);
-  gmshModelGeoAddPoint(0, 0.3, 0, 1.0, 9);
-  gmshModelGeoAddPoint(0.25, 0.2, 0, 1.0, 10);
-  gmshModelGeoAddPoint(0.3, 0.1, 0, 1.0, 11);
-  gmshModelGeoAddLine(8, 11, 10);
-  gmshModelGeoAddLine(11, 10, 11);
-  gmshModelGeoAddLine(10, 7, 12);
-  gmshModelGeoAddLine(7, 8, 13);
-  gmshModelGeoAddLineLoop({13, 10, 11, 12}, 14);
-  gmshModelGeoAddPlaneSurface({14}, 15);
+  model::geo::addPoint(0.2, 0.2, 0, 1.0, 7);
+  model::geo::addPoint(0.2, 0.1, 0, 1.0, 8);
+  model::geo::addPoint(0, 0.3, 0, 1.0, 9);
+  model::geo::addPoint(0.25, 0.2, 0, 1.0, 10);
+  model::geo::addPoint(0.3, 0.1, 0, 1.0, 11);
+  model::geo::addLine(8, 11, 10);
+  model::geo::addLine(11, 10, 11);
+  model::geo::addLine(10, 7, 12);
+  model::geo::addLine(7, 8, 13);
+  model::geo::addLineLoop({13, 10, 11, 12}, 14);
+  model::geo::addPlaneSurface({14}, 15);
   for(int i = 10; i <= 13; i++)
-    gmshModelGeoSetTransfiniteLine(i, 10);
-  gmshModelGeoSetTransfiniteSurface(15);
-  gmshModelAddPhysicalGroup(2, {15}, 2);
+    model::geo::mesh::setTransfiniteLine(i, 10);
+  model::geo::mesh::setTransfiniteSurface(15);
+
+  model::addPhysicalGroup(2, {15}, 2);
 
-  gmshModelMesh(2);
-  gmshExport("t6.msh");
-  gmshFinalize();
+  model::geo::synchronize();
+  model::mesh::generate(2);
+  write("t6.msh");
+  finalize();
   return 0;
 }
diff --git a/demos/api/t6.py b/demos/api/t6.py
index 30a5bf14cd482a97239a7918e0585d4b74ee5f7d..2c83df0bb86b216e859ffbe03d2375f04406ae58 100644
--- a/demos/api/t6.py
+++ b/demos/api/t6.py
@@ -1,89 +1,89 @@
 # This file reimplements gmsh/tutorial/t6.geo in Python.
 
-from gmsh import *
+import gmsh
 import math
 
-gmshInitialize()
-gmshOptionSetNumber("General.Terminal", 1)
+gmsh.initialize()
+gmsh.optionSetNumber("General.Terminal", 1)
 
-gmshModelCreate("t6")
+gmsh.modelAdd("t6")
 
 # Copied from t1.py...
 lc = 1e-2
-gmshModelGeoAddPoint(0, 0, 0, lc, 1)
-gmshModelGeoAddPoint(.1, 0,  0, lc, 2)
-gmshModelGeoAddPoint(.1, .3, 0, lc, 3)
-gmshModelGeoAddPoint(0, .3, 0, lc, 4)
-gmshModelGeoAddLine(1, 2, 1)
-gmshModelGeoAddLine(3, 2, 2)
-gmshModelGeoAddLine(3, 4, 3)
-gmshModelGeoAddLine(4, 1, 4)
-gmshModelGeoAddLineLoop([4, 1, -2, 3], 1)
-gmshModelGeoAddPlaneSurface([1], 1)
-gmshModelAddPhysicalGroup(0, [1, 2], 1)
-gmshModelAddPhysicalGroup(1, [1, 2], 2)
-gmshModelAddPhysicalGroup(2, [1], 6)
-gmshModelSetPhysicalName(2, 6, "My surface")
+gmsh.modelGeoAddPoint(0, 0, 0, lc, 1)
+gmsh.modelGeoAddPoint(.1, 0,  0, lc, 2)
+gmsh.modelGeoAddPoint(.1, .3, 0, lc, 3)
+gmsh.modelGeoAddPoint(0, .3, 0, lc, 4)
+gmsh.modelGeoAddLine(1, 2, 1)
+gmsh.modelGeoAddLine(3, 2, 2)
+gmsh.modelGeoAddLine(3, 4, 3)
+gmsh.modelGeoAddLine(4, 1, 4)
+gmsh.modelGeoAddLineLoop([4, 1, -2, 3], 1)
+gmsh.modelGeoAddPlaneSurface([1], 1)
+gmsh.modelAddPhysicalGroup(0, [1, 2], 1)
+gmsh.modelAddPhysicalGroup(1, [1, 2], 2)
+gmsh.modelAddPhysicalGroup(2, [1], 6)
+gmsh.modelSetPhysicalName(2, 6, "My surface")
 # ...end of copy
 
 # Delete surface 1 and left boundary (line 4)
-gmshModelGeoRemove([[2,1], [1,4]])
+gmsh.modelGeoRemove([[2,1], [1,4]])
 
 # Replace left boundary with 3 new lines
-p1 = gmshModelGeoAddPoint(-0.05, 0.05, 0, lc)
-p2 = gmshModelGeoAddPoint(-0.05, 0.1, 0, lc)
-l1 = gmshModelGeoAddLine(1, p1)
-l2 = gmshModelGeoAddLine(p1, p2)
-l3 = gmshModelGeoAddLine(p2, 4)
+p1 = gmsh.modelGeoAddPoint(-0.05, 0.05, 0, lc)
+p2 = gmsh.modelGeoAddPoint(-0.05, 0.1, 0, lc)
+l1 = gmsh.modelGeoAddLine(1, p1)
+l2 = gmsh.modelGeoAddLine(p1, p2)
+l3 = gmsh.modelGeoAddLine(p2, 4)
 
 # Recreate surface
-gmshModelGeoAddLineLoop([2, -1, l1, l2, l3, -3], 2)
-gmshModelGeoAddPlaneSurface([-2], 1)
+gmsh.modelGeoAddLineLoop([2, -1, l1, l2, l3, -3], 2)
+gmsh.modelGeoAddPlaneSurface([-2], 1)
 
 # Put 20 points with a refinement toward the extremities on curve 2
-gmshModelGeoSetTransfiniteLine(2, 20, "Bump", 0.05)
+gmsh.modelGeoMeshSetTransfiniteLine(2, 20, "Bump", 0.05)
 
 # Put 20 points total on combination of curves l1, l2 and l3 (beware that the
 # points p1 and p2 are shared by the curves, so we do not create 6 + 6 + 10 = 22
 # points, but 20!)
-gmshModelGeoSetTransfiniteLine(l1, 6)
-gmshModelGeoSetTransfiniteLine(l2, 6)
-gmshModelGeoSetTransfiniteLine(l3, 10)
+gmsh.modelGeoMeshSetTransfiniteLine(l1, 6)
+gmsh.modelGeoMeshSetTransfiniteLine(l2, 6)
+gmsh.modelGeoMeshSetTransfiniteLine(l3, 10)
 
 # Put 30 points following a geometric progression on curve 1 (reversed) and on
 # curve 3
-gmshModelGeoSetTransfiniteLine(1, 30, "Progression", -1.2)
-gmshModelGeoSetTransfiniteLine(3, 30, "Progression", 1.2)
+gmsh.modelGeoMeshSetTransfiniteLine(1, 30, "Progression", -1.2)
+gmsh.modelGeoMeshSetTransfiniteLine(3, 30, "Progression", 1.2)
 
 # Define the Surface as transfinite, by specifying the four corners of the
 # transfinite interpolation
-gmshModelGeoSetTransfiniteSurface(1, "Left", [1,2,3,4])
+gmsh.modelGeoMeshSetTransfiniteSurface(1, "Left", [1,2,3,4])
 
 # Recombine the triangles into quads
-gmshModelGeoSetRecombine(2, 1)
+gmsh.modelGeoMeshSetRecombine(2, 1)
 
 # Apply an elliptic smoother to the grid
-gmshOptionSetNumber("Mesh.Smoothing", 100)
-gmshModelAddPhysicalGroup(2, [1], 1)
+gmsh.optionSetNumber("Mesh.Smoothing", 100)
+gmsh.modelAddPhysicalGroup(2, [1], 1)
 
 # When the surface has only 3 or 4 control points, the transfinite constraint
 # can be applied automatically (without specifying the corners explictly).
-gmshModelGeoAddPoint(0.2, 0.2, 0, 1.0, 7)
-gmshModelGeoAddPoint(0.2, 0.1, 0, 1.0, 8)
-gmshModelGeoAddPoint(0, 0.3, 0, 1.0, 9)
-gmshModelGeoAddPoint(0.25, 0.2, 0, 1.0, 10)
-gmshModelGeoAddPoint(0.3, 0.1, 0, 1.0, 11)
-gmshModelGeoAddLine(8, 11, 10)
-gmshModelGeoAddLine(11, 10, 11)
-gmshModelGeoAddLine(10, 7, 12)
-gmshModelGeoAddLine(7, 8, 13)
-gmshModelGeoAddLineLoop([13, 10, 11, 12], 14)
-gmshModelGeoAddPlaneSurface([14], 15)
+gmsh.modelGeoAddPoint(0.2, 0.2, 0, 1.0, 7)
+gmsh.modelGeoAddPoint(0.2, 0.1, 0, 1.0, 8)
+gmsh.modelGeoAddPoint(0, 0.3, 0, 1.0, 9)
+gmsh.modelGeoAddPoint(0.25, 0.2, 0, 1.0, 10)
+gmsh.modelGeoAddPoint(0.3, 0.1, 0, 1.0, 11)
+gmsh.modelGeoAddLine(8, 11, 10)
+gmsh.modelGeoAddLine(11, 10, 11)
+gmsh.modelGeoAddLine(10, 7, 12)
+gmsh.modelGeoAddLine(7, 8, 13)
+gmsh.modelGeoAddLineLoop([13, 10, 11, 12], 14)
+gmsh.modelGeoAddPlaneSurface([14], 15)
 for i in range(10,14):
-    gmshModelGeoSetTransfiniteLine(i, 10)
-gmshModelGeoSetTransfiniteSurface(15)
-gmshModelAddPhysicalGroup(2, [15], 2)
+    gmsh.modelGeoMeshSetTransfiniteLine(i, 10)
+gmsh.modelGeoMeshSetTransfiniteSurface(15)
+gmsh.modelAddPhysicalGroup(2, [15], 2)
 
-gmshModelMesh(2)
-gmshExport("t6.msh")
-gmshFinalize()
+gmsh.modelMeshGenerate(2)
+gmsh.write("t6.msh")
+gmsh.finalize()
diff --git a/demos/api/view.cpp b/demos/api/view.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..dad52aa137cae39cc39c41051819549f3c361c59
--- /dev/null
+++ b/demos/api/view.cpp
@@ -0,0 +1,36 @@
+#include <gmsh.h>
+
+int main(int argc, char **argv)
+{
+  gmsh::initialize();
+  gmsh::option::setNumber("General.Terminal", 1);
+
+  // Copied from discrete.cpp...
+  gmsh::model::add("test");
+  gmsh::model::addDiscreteEntity(2, 1);
+  gmsh::model::mesh::setVertices(2, 1, {1, 2, 3, 4},
+                                 {0., 0., 0.,
+                                  1., 0., 0.,
+                                  1., 1., 0.,
+                                  0., 1., 0.});
+  gmsh::model::mesh::setElements(2, 1, {2}, {{1, 2}},
+                                 {{1, 2, 3,
+                                   1, 3, 4}});
+  // ... end of copy
+
+  // Create a new post-processing view
+  int t = gmsh::view::add("some data");
+
+  // add 10 steps of model-based data, on the nodes of the mesh
+  for(int step = 0; step < 10; step++)
+    gmsh::view::addModelData(t, "test", "NodeData",
+                             {1, 2, 3, 4}, // tags of nodes
+                             {{10.},{10.},{12.+step},{13.+step}}, // data, per node
+                             step);
+
+  gmsh::view::write(t, "data.msh");
+
+  gmsh::finalize();
+  return 0;
+}
+
diff --git a/demos/api/view.py b/demos/api/view.py
new file mode 100644
index 0000000000000000000000000000000000000000..55bb11784ff2e6aabe7e43d97687f85754c5bb4a
--- /dev/null
+++ b/demos/api/view.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+
+import gmsh
+import sys
+
+gmsh.initialize(sys.argv)
+gmsh.optionSetNumber("General.Terminal", 1)
+
+# Copied from discrete.py...
+gmsh.modelAdd("test");
+gmsh.modelAddDiscreteEntity(2, 1)
+gmsh.modelMeshSetVertices(2, 1, [1, 2, 3, 4],
+                         [0., 0., 0.,
+                          1., 0., 0.,
+                          1., 1., 0.,
+                          0., 1., 0.])
+gmsh.modelMeshSetElements(2, 1, [2], [[1, 2]],
+                         [[1, 2, 3,
+                           1, 3, 4]])
+# ... end of copy
+
+# Create a new post-processing view
+t = gmsh.viewAdd("some data")
+
+# add 10 steps of model-based data, on the nodes of the mesh
+for step in range(0, 10):
+    gmsh.viewAddModelData(t, "test", "NodeData",
+                         [1, 2, 3, 4], # tags of nodes
+                         [[10.],[10.],[12.+step],[13.+step]], # data, per node
+                         step)
+    
+gmsh.viewWrite(t, "data.msh")
+    
+gmsh.finalize()
diff --git a/demos/api/viewlist.cpp b/demos/api/viewlist.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..eabc7d1fa045f0796b66fe0128e0bf4f5261e61b
--- /dev/null
+++ b/demos/api/viewlist.cpp
@@ -0,0 +1,35 @@
+#include <gmsh.h>
+
+int main(int argc, char **argv)
+{
+  gmsh::initialize();
+  gmsh::option::setNumber("General.Terminal", 1);
+
+  std::vector<double> tri1 = {0., 1., 1.,
+                              0., 0., 1.,
+                              0., 0., 0.};
+  std::vector<double> tri2 = {0., 1., 0.,
+                              0., 1., 1.,
+                              0., 0., 0.};
+
+  for(int step = 0; step < 10; step++){
+    tri1.push_back(10.);
+    tri1.push_back(10.);
+    tri1.push_back(12. + step);
+    tri2.push_back(10.);
+    tri2.push_back(12. + step);
+    tri2.push_back(13. + step);
+  }
+
+  int t = gmsh::view::add("some data");
+  std::vector<double> data;
+  data.insert(data.end(), tri1.begin(), tri1.end());
+  data.insert(data.end(), tri2.begin(), tri2.end());
+
+  gmsh::view::addListData(t, "ST", 2, data);
+
+  gmsh::view::write(t, "data.pos");
+
+  gmsh::finalize();
+  return 0;
+}
diff --git a/demos/api/viewlist.py b/demos/api/viewlist.py
new file mode 100644
index 0000000000000000000000000000000000000000..a2532de287240341a5bef60c394806e95d5f7616
--- /dev/null
+++ b/demos/api/viewlist.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python
+
+import gmsh
+import sys
+
+gmsh.initialize(sys.argv)
+gmsh.optionSetNumber("General.Terminal", 1)
+
+tri1 = [0., 1., 1.,
+        0., 0., 1.,
+        0., 0., 0.];
+tri2 = [0., 1., 0.,
+        0., 1., 1.,
+        0., 0., 0.];
+
+for step in range(0, 10):
+    tri1.append(10.); tri1.append(10.); tri1.append(12. + step)
+    tri2.append(10.); tri2.append(12. + step); tri2.append(13. + step)
+
+t = gmsh.viewAdd("some data")
+
+gmsh.viewAddListData(t, "ST", 2, tri1 + tri2)
+
+gmsh.viewWrite(t, "data.pos")
+
+gmsh.finalize()
diff --git a/doc/texinfo/opt_geometry.texi b/doc/texinfo/opt_geometry.texi
index a918f85f328ab47ad3937f4386a24c2c5bbe25ee..921b20a219e21aefeee567f2bef0ef11490eec5b 100644
--- a/doc/texinfo/opt_geometry.texi
+++ b/doc/texinfo/opt_geometry.texi
@@ -59,11 +59,6 @@ Number of control points for splines created during extrusion@*
 Default value: @code{5}@*
 Saved in: @code{General.OptionsFileName}
 
-@item Geometry.HideCompounds
-Hide entities that make up compound entities?@*
-Default value: @code{1}@*
-Saved in: @code{General.OptionsFileName}
-
 @item Geometry.HighlightOrphans
 Highlight orphan entities (lines connected to a single surface, etc.)?@*
 Default value: @code{0}@*
diff --git a/doc/texinfo/opt_post.texi b/doc/texinfo/opt_post.texi
index 58f754bbe9d4b5e6f6a2ca90d8977dc5a9a90927..6922e34c9fcc6e0ca5109a1699cd1873651e01d6 100644
--- a/doc/texinfo/opt_post.texi
+++ b/doc/texinfo/opt_post.texi
@@ -94,6 +94,16 @@ Enable default post-processing plugins?@*
 Default value: @code{1}@*
 Saved in: @code{General.OptionsFileName}
 
+@item PostProcessing.SaveInterpolationMatrices
+Save the interpolation matrices when exporting model-based data@*
+Default value: @code{1}@*
+Saved in: @code{General.OptionsFileName}
+
+@item PostProcessing.SaveMesh
+Save the mesh when exporting model-based data@*
+Default value: @code{1}@*
+Saved in: @code{General.OptionsFileName}
+
 @item PostProcessing.Smoothing
 Apply (non-reversible) smoothing to post-processing view when merged@*
 Default value: @code{0}@*
diff --git a/utils/misc/package_onelab.sh b/utils/misc/package_onelab.sh
index 14fa544a8fbd3f5c901761fd1baa2e9c87cf87da..d7f211ebc237ef1da23d23a1bade9e8c237c283f 100755
--- a/utils/misc/package_onelab.sh
+++ b/utils/misc/package_onelab.sh
@@ -70,17 +70,17 @@ if [ $# -lt 1 ] || [ $1 == "win64" ]; then
   unzip -q -o /tmp/getdp-${GETDP}-Windows64c.zip -d /tmp
   cp /tmp/README.txt onelab-Windows64
   perl -pi -e 's/\n/\r\n/' onelab-Windows64/README.txt
-  mv /tmp/gmsh-*${GMSH}-Windows/gmsh.exe onelab-Windows64
-  mv /tmp/gmsh-*${GMSH}-Windows/onelab.py onelab-Windows64
-  mv /tmp/getdp-*${GETDP}-Windows/getdp.exe onelab-Windows64
-  mv /tmp/gmsh-*${GMSH}-Windows/LICENSE.txt onelab-Windows64/LICENSE.txt
+  mv /tmp/gmsh-*${GMSH}-Windows64/gmsh.exe onelab-Windows64
+  mv /tmp/gmsh-*${GMSH}-Windows64/onelab.py onelab-Windows64
+  mv /tmp/getdp-*${GETDP}-Windows64/getdp.exe onelab-Windows64
+  mv /tmp/gmsh-*${GMSH}-Windows64/LICENSE.txt onelab-Windows64/LICENSE.txt
   echo "\n\n" >> onelab-Windows64/LICENSE.txt
-  cat /tmp/getdp-*${GETDP}-Windows/LICENSE.txt >> onelab-Windows64/LICENSE.txt
-  mv /tmp/gmsh-*${GMSH}-Windows/CREDITS.txt onelab-Windows64/CREDITS.txt
+  cat /tmp/getdp-*${GETDP}-Windows64/LICENSE.txt >> onelab-Windows64/LICENSE.txt
+  mv /tmp/gmsh-*${GMSH}-Windows64/CREDITS.txt onelab-Windows64/CREDITS.txt
   echo "\n\n" >> onelab-Windows64/CREDITS.txt
-  cat /tmp/getdp-*${GETDP}-Windows/CREDITS.txt >> onelab-Windows64/CREDITS.txt
-  mv /tmp/getdp-*${GETDP}-Windows/templates onelab-Windows64
-  mv /tmp/gmsh-*${GMSH}-Windows/tutorial onelab-Windows64
+  cat /tmp/getdp-*${GETDP}-Windows64/CREDITS.txt >> onelab-Windows64/CREDITS.txt
+  mv /tmp/getdp-*${GETDP}-Windows64/templates onelab-Windows64
+  mv /tmp/gmsh-*${GMSH}-Windows64/tutorial onelab-Windows64
   cp -R /tmp/models onelab-Windows64
   rm -rf /tmp/gmsh-*
   rm -rf /tmp/getdp-*
@@ -99,17 +99,17 @@ if [ $# -lt 1 ] || [ $1 == "win32" ]; then
   unzip -q -o /tmp/getdp-${GETDP}-Windows32c.zip -d /tmp
   cp /tmp/README.txt onelab-Windows32
   perl -pi -e 's/\n/\r\n/' onelab-Windows32/README.txt
-  mv /tmp/gmsh-*${GMSH}-Windows/gmsh.exe onelab-Windows32
-  mv /tmp/gmsh-*${GMSH}-Windows/onelab.py onelab-Windows32
-  mv /tmp/getdp-*${GETDP}-Windows/getdp.exe onelab-Windows32
-  mv /tmp/gmsh-*${GMSH}-Windows/LICENSE.txt onelab-Windows32/LICENSE.txt
+  mv /tmp/gmsh-*${GMSH}-Windows32/gmsh.exe onelab-Windows32
+  mv /tmp/gmsh-*${GMSH}-Windows32/onelab.py onelab-Windows32
+  mv /tmp/getdp-*${GETDP}-Windows32/getdp.exe onelab-Windows32
+  mv /tmp/gmsh-*${GMSH}-Windows32/LICENSE.txt onelab-Windows32/LICENSE.txt
   echo "\n\n" >> onelab-Windows32/LICENSE.txt
-  cat /tmp/getdp-*${GETDP}-Windows/LICENSE.txt >> onelab-Windows32/LICENSE.txt
-  mv /tmp/gmsh-*${GMSH}-Windows/CREDITS.txt onelab-Windows32/CREDITS.txt
+  cat /tmp/getdp-*${GETDP}-Windows32/LICENSE.txt >> onelab-Windows32/LICENSE.txt
+  mv /tmp/gmsh-*${GMSH}-Windows32/CREDITS.txt onelab-Windows32/CREDITS.txt
   echo "\n\n" >> onelab-Windows32/CREDITS.txt
-  cat /tmp/getdp-*${GETDP}-Windows/CREDITS.txt >> onelab-Windows32/CREDITS.txt
-  mv /tmp/getdp-*${GETDP}-Windows/templates onelab-Windows32
-  mv /tmp/gmsh-*${GMSH}-Windows/tutorial onelab-Windows32
+  cat /tmp/getdp-*${GETDP}-Windows32/CREDITS.txt >> onelab-Windows32/CREDITS.txt
+  mv /tmp/getdp-*${GETDP}-Windows32/templates onelab-Windows32
+  mv /tmp/gmsh-*${GMSH}-Windows32/tutorial onelab-Windows32
   cp -R /tmp/models onelab-Windows32
   rm -rf /tmp/gmsh-*
   rm -rf /tmp/getdp-*
@@ -127,17 +127,17 @@ if [ $# -lt 1 ] || [ $1 == "linux64" ]; then
   tar zxvf /tmp/gmsh-${GMSH}-Linux64.tgz -C /tmp
   tar zxvf /tmp/getdp-${GETDP}-Linux64c.tgz -C /tmp
   cp /tmp/README.txt onelab-Linux64
-  mv /tmp/gmsh-*${GMSH}-Linux/bin/gmsh onelab-Linux64
-  mv /tmp/gmsh-*${GMSH}-Linux/bin/onelab.py onelab-Linux64
-  mv /tmp/getdp-*${GETDP}-Linux/bin/getdp onelab-Linux64
-  mv /tmp/gmsh-*${GMSH}-Linux/share/doc/gmsh/LICENSE.txt onelab-Linux64/LICENSE.txt
+  mv /tmp/gmsh-*${GMSH}-Linux64/bin/gmsh onelab-Linux64
+  mv /tmp/gmsh-*${GMSH}-Linux64/bin/onelab.py onelab-Linux64
+  mv /tmp/getdp-*${GETDP}-Linux64/bin/getdp onelab-Linux64
+  mv /tmp/gmsh-*${GMSH}-Linux64/share/doc/gmsh/LICENSE.txt onelab-Linux64/LICENSE.txt
   echo "\n\n" >> onelab-Linux64/LICENSE.txt
-  cat /tmp/getdp-*${GETDP}-Linux/share/doc/getdp/LICENSE.txt >> onelab-Linux64/LICENSE.txt
-  mv /tmp/gmsh-*${GMSH}-Linux/share/doc/gmsh/CREDITS.txt onelab-Linux64/CREDITS.txt
+  cat /tmp/getdp-*${GETDP}-Linux64/share/doc/getdp/LICENSE.txt >> onelab-Linux64/LICENSE.txt
+  mv /tmp/gmsh-*${GMSH}-Linux64/share/doc/gmsh/CREDITS.txt onelab-Linux64/CREDITS.txt
   echo "\n\n" >> onelab-Linux64/CREDITS.txt
-  cat /tmp/getdp-*${GETDP}-Linux/share/doc/getdp/CREDITS.txt >> onelab-Linux64/CREDITS.txt
-  mv /tmp/getdp-*${GETDP}-Linux/share/doc/getdp/templates onelab-Linux64
-  mv /tmp/gmsh-*${GMSH}-Linux/share/doc/gmsh/tutorial onelab-Linux64
+  cat /tmp/getdp-*${GETDP}-Linux64/share/doc/getdp/CREDITS.txt >> onelab-Linux64/CREDITS.txt
+  mv /tmp/getdp-*${GETDP}-Linux64/share/doc/getdp/templates onelab-Linux64
+  mv /tmp/gmsh-*${GMSH}-Linux64/share/doc/gmsh/tutorial onelab-Linux64
   cp -R /tmp/models onelab-Linux64
   rm -rf /tmp/gmsh-*
   rm -rf /tmp/getdp-*
@@ -158,7 +158,7 @@ if [ $# -lt 1 ] || [ $1 == "mac" ]; then
   cp /tmp/README.txt onelab-MacOSX
   cp -R gmsh_mount/Gmsh.app onelab-MacOSX
   mv /tmp/getdp-*${GETDP}-MacOSX/bin/getdp onelab-MacOSX/Gmsh.app/Contents/MacOS/
-  security unlock-keychain -p "FIXME" ${HOME}/Library/Keychains/login.keychain
+  security unlock-keychain -p "FIXME!" ${HOME}/Library/Keychains/login.keychain
   codesign -v --force --deep --sign "Developer ID Application: Christophe Geuzaine" onelab-MacOSX/Gmsh.app
   cp gmsh_mount/LICENSE.txt onelab-MacOSX/LICENSE.txt
   echo "\n\n" >> onelab-MacOSX/LICENSE.txt