From af8b00673af07fc108cd3e5a968e52790f1d319f Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Tue, 4 Jun 2019 19:08:01 +0200
Subject: [PATCH] API change: replaced setNodes/setElements by
 addNodes/addElements + added new mesh::clear()

Rationale: setNodes/setElements were intrinsically a bad design choice,
as these functions had to delete nodes and/or elements before storing the
new ones. Using these functions in the wrong way could lead to an invalid
mesh, with elements pointing to nodes that were deleted (in an adjacent
entity).

The only viable workflow is to delete the mesh (with the new clear()
function), before adding nodes/elements.
---
 CHANGELOG.txt                         | 13 +++---
 Common/gmsh.cpp                       | 25 +++++++-----
 api/GenApi.py                         |  2 +-
 api/api.texi                          | 53 +++++++++++++++---------
 api/gen.py                            | 15 ++++---
 api/gmsh.h                            | 35 ++++++++--------
 api/gmsh.h_cwrap                      | 46 ++++++++++++---------
 api/gmsh.jl                           | 56 ++++++++++++++++----------
 api/gmsh.py                           | 58 +++++++++++++++++----------
 api/gmshc.cpp                         | 23 ++++++++---
 api/gmshc.h                           | 34 +++++++++-------
 demos/api/discrete.cpp                |  4 +-
 demos/api/discrete.jl                 |  5 +--
 demos/api/discrete.py                 |  5 +--
 demos/api/edges.cpp                   |  2 +-
 demos/api/faces.cpp                   |  2 +-
 demos/api/mesh_from_discrete_curve.py |  4 +-
 demos/api/plugin.cpp                  |  4 +-
 demos/api/plugin.py                   |  4 +-
 demos/api/test.py                     |  2 +-
 demos/api/view.cpp                    |  4 +-
 demos/api/view.py                     |  8 ++--
 doc/texinfo/api.texi                  | 53 +++++++++++++++---------
 23 files changed, 271 insertions(+), 186 deletions(-)

diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index ff58fceeee..e753383375 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -1,11 +1,12 @@
 4.4.0: new STL remeshing workflow; added API support for color options, mesh
 optimization, recombination, smoothing and shape healing; changed getJacobians
-and getBasisFunctions API to specify integration points explicitely; exposed
-additional METIS options; improved support for periodic entities (multiple
-curves with the same start/end points; legacy MSH2 format); added mesh
-renumbering also after interactive mesh modifications; new interactive filter in
-visibility window; modernized GUI with slightly "flatter" scheme; small bug
-fixes.
+and getBasisFunctions API to specify integration points explicitely; changed API
+for storing nodes and elements (set{Nodes,Elements} replaced by
+add{Nodes,Elements}); exposed additional METIS options; improved support for
+periodic entities (multiple curves with the same start/end points; legacy MSH2
+format); added mesh renumbering also after interactive mesh modifications; new
+interactive filter in visibility window; modernized GUI with slightly "flatter"
+scheme; small bug fixes.
 
 4.3.0 (April 19, 2019): improved meshing of surfaces with singular
 parametrizations; added API support for aliasing and combining views, copying
diff --git a/Common/gmsh.cpp b/Common/gmsh.cpp
index be3f9deea5..47926841e7 100644
--- a/Common/gmsh.cpp
+++ b/Common/gmsh.cpp
@@ -942,6 +942,12 @@ gmsh::model::mesh::getLastNodeError(std::vector<std::size_t> &nodeTags)
   for(std::size_t i = 0; i < v.size(); i++) nodeTags.push_back(v[i]->getNum());
 }
 
+GMSH_API void gmsh::model::mesh::clear()
+{
+  if(!_isInitialized()) { throw -1; }
+  GModel::current()->deleteMesh();
+}
+
 static void _getAdditionalNodesOnBoundary(GEntity *entity,
                                           std::vector<std::size_t> &nodeTags,
                                           std::vector<double> &coord,
@@ -1160,7 +1166,7 @@ gmsh::model::mesh::getNodesForPhysicalGroup(const int dim, const int tag,
   }
 }
 
-GMSH_API void gmsh::model::mesh::setNodes(
+GMSH_API void gmsh::model::mesh::addNodes(
   const int dim, const int tag, const std::vector<std::size_t> &nodeTags,
   const std::vector<double> &coord, const std::vector<double> &parametricCoord)
 {
@@ -1186,25 +1192,23 @@ GMSH_API void gmsh::model::mesh::setNodes(
     }
     param = true;
   }
-  // delete nodes and elements; this will also delete the model mesh cache
-  ge->deleteMesh();
   for(int i = 0; i < numNodes; i++) {
-    std::size_t n = (numNodeTags ? nodeTags[i] : 0); // 0 = automatic tag
+    std::size_t tag = (numNodeTags ? nodeTags[i] : 0); // 0 = automatic tag
     double x = coord[3 * i];
     double y = coord[3 * i + 1];
     double z = coord[3 * i + 2];
     MVertex *vv = 0;
     if(param && dim == 1) {
       double u = parametricCoord[i];
-      vv = new MEdgeVertex(x, y, z, ge, u, n);
+      vv = new MEdgeVertex(x, y, z, ge, u, tag);
     }
     else if(param && dim == 2) {
       double u = parametricCoord[2 * i];
       double v = parametricCoord[2 * i + 1];
-      vv = new MFaceVertex(x, y, z, ge, u, v, n);
+      vv = new MFaceVertex(x, y, z, ge, u, v, tag);
     }
     else
-      vv = new MVertex(x, y, z, ge, n);
+      vv = new MVertex(x, y, z, ge, tag);
     ge->mesh_vertices.push_back(vv);
   }
 }
@@ -1453,7 +1457,7 @@ static void _addElements(int dim, int tag, GEntity *ge, int type,
   }
 }
 
-GMSH_API void gmsh::model::mesh::setElements(
+GMSH_API void gmsh::model::mesh::addElements(
   const int dim, const int tag, const std::vector<int> &elementTypes,
   const std::vector<std::vector<std::size_t> > &elementTags,
   const std::vector<std::vector<std::size_t> > &nodeTags)
@@ -1472,13 +1476,12 @@ GMSH_API void gmsh::model::mesh::setElements(
     Msg::Error("Wrong number of node tags");
     throw 2;
   }
-  // delete only elements; this will also delete the model mesh cache
-  ge->deleteMesh(true);
+
   for(std::size_t i = 0; i < elementTypes.size(); i++)
     _addElements(dim, tag, ge, elementTypes[i], elementTags[i], nodeTags[i]);
 }
 
-GMSH_API void gmsh::model::mesh::setElementsByType(
+GMSH_API void gmsh::model::mesh::addElementsByType(
   const int tag, const int elementType,
   const std::vector<std::size_t> &elementTags,
   const std::vector<std::size_t> &nodeTags)
diff --git a/api/GenApi.py b/api/GenApi.py
index b58d074a60..e44ea14e66 100644
--- a/api/GenApi.py
+++ b/api/GenApi.py
@@ -1025,7 +1025,7 @@ def _ovectorvectorint(ptr, size, n):
     return v
 
 def _ovectorvectorsize(ptr, size, n):
-    v = [_ovectorint(pointer(ptr[i].contents), size[i]) for i in range(n.value)]
+    v = [_ovectorsize(pointer(ptr[i].contents), size[i]) for i in range(n.value)]
     lib.{6}Free(size)
     lib.{6}Free(ptr)
     return v
diff --git a/api/api.texi b/api/api.texi
index f6bafb4d99..68b6ceee56 100644
--- a/api/api.texi
+++ b/api/api.texi
@@ -811,6 +811,18 @@ populated by the new 3D meshing algorithms.
 -
 @end table
 
+@item clear
+Clear the mesh, i.e. delete all the nodes and elements.
+
+@table @asis
+@item Input:
+-
+@item Output:
+-
+@item Return:
+-
+@end table
+
 @item getNodes
 Get the nodes classified on the entity of dimension @code{dim} and tag
 @code{tag}. If @code{tag} < 0, get the nodes for all entities of dimension
@@ -894,8 +906,8 @@ n2x, ...].
 -
 @end table
 
-@item setNodes
-Set the nodes classified on the model entity of dimension @code{dim} and tag
+@item addNodes
+Add nodes classified on the model entity of dimension @code{dim} and tag
 @code{tag}. @code{nodeTags} contains the node tags (their unique, strictly
 positive identification numbers). @code{coord} is a vector of length 3 times the
 length of @code{nodeTags} that contains the x, y, z coordinates of the nodes,
@@ -1081,16 +1093,17 @@ Preallocate data before calling @code{getElementsByType} with @code{numTasks} >
 -
 @end table
 
-@item setElements
-Set the elements of the entity of dimension @code{dim} and tag @code{tag}.
-@code{types} contains the MSH types of the elements (e.g. @code{2} for 3-node
-triangles: see the Gmsh reference manual). @code{elementTags} is a vector of the
-same length as @code{types}; each entry is a vector containing the tags (unique,
-strictly positive identifiers) of the elements of the corresponding type.
-@code{nodeTags} is also a vector of the same length as @code{types}; each entry
-is a vector of length equal to the number of elements of the given type times
-the number N of nodes per element, that contains the node tags of all the
-elements of the given type, concatenated: [e1n1, e1n2, ..., e1nN, e2n1, ...].
+@item addElements
+Add elements classified on the entity of dimension @code{dim} and tag
+@code{tag}. @code{types} contains the MSH types of the elements (e.g. @code{2}
+for 3-node triangles: see the Gmsh reference manual). @code{elementTags} is a
+vector of the same length as @code{types}; each entry is a vector containing the
+tags (unique, strictly positive identifiers) of the elements of the
+corresponding type. @code{nodeTags} is also a vector of the same length as
+@code{types}; each entry is a vector of length equal to the number of elements
+of the given type times the number N of nodes per element, that contains the
+node tags of all the elements of the given type, concatenated: [e1n1, e1n2, ...,
+e1nN, e2n1, ...].
 
 @table @asis
 @item Input:
@@ -1101,14 +1114,14 @@ elements of the given type, concatenated: [e1n1, e1n2, ..., e1nN, e2n1, ...].
 -
 @end table
 
-@item setElementsByType
-Set the elements of type @code{elementType} in the entity of tag @code{tag}.
-@code{elementTags} contains the tags (unique, strictly positive identifiers) of
-the elements of the corresponding type. @code{nodeTags} is a vector of length
-equal to the number of elements times the number N of nodes per element, that
-contains the node tags of all the elements, concatenated: [e1n1, e1n2, ...,
-e1nN, e2n1, ...]. If the @code{elementTag} vector is empty, new tags are
-automatically assigned to the elements.
+@item addElementsByType
+Add elements of type @code{elementType} classified on the entity of tag
+@code{tag}. @code{elementTags} contains the tags (unique, strictly positive
+identifiers) of the elements of the corresponding type. @code{nodeTags} is a
+vector of length equal to the number of elements times the number N of nodes per
+element, that contains the node tags of all the elements, concatenated: [e1n1,
+e1n2, ..., e1nN, e2n1, ...]. If the @code{elementTag} vector is empty, new tags
+are automatically assigned to the elements.
 
 @table @asis
 @item Input:
diff --git a/api/gen.py b/api/gen.py
index 03ce6bbbe4..a83972c241 100644
--- a/api/gen.py
+++ b/api/gen.py
@@ -225,6 +225,9 @@ mesh.add('getLastEntityError',doc,None,ovectorpair('dimTags'))
 doc = '''Get the last nodes (if any) where a meshing error occurred. Currently only populated by the new 3D meshing algorithms.'''
 mesh.add('getLastNodeError',doc,None,ovectorsize('nodeTags'))
 
+doc = '''Clear the mesh, i.e. delete all the nodes and elements.'''
+mesh.add('clear',doc,None)
+
 doc = '''Get the nodes classified on the entity of dimension `dim' and tag `tag'. If `tag' < 0, get the nodes for all entities of dimension `dim'. If `dim' and `tag' are negative, get all the nodes in the mesh. `nodeTags' contains the node tags (their unique, strictly positive identification numbers). `coord' is a vector of length 3 times the length of `nodeTags' that contains the x, y, z coordinates of the nodes, concatenated: [n1x, n1y, n1z, n2x, ...]. If `dim' >= 0 and `returnParamtricCoord' is set, `parametricCoord' contains the parametric coordinates ([u1, u2, ...] or [u1, v1, u2, ...]) of the nodes, if available. The length of `parametricCoord' can be 0 or `dim' times the length of `nodeTags'. If `includeBoundary' is set, also return the nodes classified on the boundary of the entity (which will be reparametrized on the entity if `dim' >= 0 in order to compute their parametric coordinates).'''
 mesh.add('getNodes',doc,None,ovectorsize('nodeTags'),ovectordouble('coord'),ovectordouble('parametricCoord'),iint('dim', '-1'),iint('tag', '-1'),ibool('includeBoundary','false','False'),ibool('returnParametricCoord','true','True'))
 
@@ -240,8 +243,8 @@ mesh.add('rebuildNodeCache',doc,None,ibool('onlyIfNecessary', 'true', 'True'))
 doc = '''Get the nodes from all the elements belonging to the physical group of dimension `dim' and tag `tag'. `nodeTags' contains the node tags; `coord' is a vector of length 3 times the length of `nodeTags' that contains the x, y, z coordinates of the nodes, concatenated: [n1x, n1y, n1z, n2x, ...].'''
 mesh.add('getNodesForPhysicalGroup',doc,None,iint('dim'),iint('tag'),ovectorsize('nodeTags'),ovectordouble('coord'))
 
-doc = '''Set the nodes classified on the model entity of dimension `dim' and tag `tag'. `nodeTags' contains the node tags (their unique, strictly positive identification numbers). `coord' is a vector of length 3 times the length of `nodeTags' that contains the x, y, z coordinates of the nodes, concatenated: [n1x, n1y, n1z, n2x, ...]. The optional `parametricCoord' vector contains the parametric coordinates of the nodes, if any. The length of `parametricCoord' can be 0 or `dim' times the length of `nodeTags'. If the `nodeTags' vector is empty, new tags are automatically assigned to the nodes.'''
-mesh.add('setNodes',doc,None,iint('dim'),iint('tag'),ivectorsize('nodeTags'),ivectordouble('coord'),ivectordouble('parametricCoord','std::vector<double>()',"[]","[]"))
+doc = '''Add nodes classified on the model entity of dimension `dim' and tag `tag'. `nodeTags' contains the node tags (their unique, strictly positive identification numbers). `coord' is a vector of length 3 times the length of `nodeTags' that contains the x, y, z coordinates of the nodes, concatenated: [n1x, n1y, n1z, n2x, ...]. The optional `parametricCoord' vector contains the parametric coordinates of the nodes, if any. The length of `parametricCoord' can be 0 or `dim' times the length of `nodeTags'. If the `nodeTags' vector is empty, new tags are automatically assigned to the nodes.'''
+mesh.add('addNodes',doc,None,iint('dim'),iint('tag'),ivectorsize('nodeTags'),ivectordouble('coord'),ivectordouble('parametricCoord','std::vector<double>()',"[]","[]"))
 
 doc = '''Reclassify all nodes on their associated model entity, based on the elements. Can be used when importing nodes in bulk (e.g. by associating them all to a single volume), to reclassify them correctly on model surfaces, curves, etc. after the elements have been set.'''
 mesh.add('reclassifyNodes',doc,None)
@@ -273,11 +276,11 @@ mesh.add('getElementsByType',doc,None,iint('elementType'),ovectorsize('elementTa
 doc = '''Preallocate data before calling `getElementsByType' with `numTasks' > 1. For C and C++ only.'''
 mesh.add_special('preallocateElementsByType',doc,['onlycc++'],None,iint('elementType'),ibool('elementTag'),ibool('nodeTag'),ovectorsize('elementTags'),ovectorsize('nodeTags'),iint('tag', '-1'))
 
-doc = '''Set the 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 the same length as `types'; each entry is a vector containing the tags (unique, strictly positive identifiers) of the elements of the corresponding type. `nodeTags' is also a vector of the same length as `types'; each entry is a vector of length equal to the number of elements of the given type times the number N of nodes per element, that contains the node tags of all the elements of the given type, concatenated: [e1n1, e1n2, ..., e1nN, e2n1, ...].'''
-mesh.add('setElements',doc,None,iint('dim'),iint('tag'),ivectorint('elementTypes'),ivectorvectorsize('elementTags'),ivectorvectorsize('nodeTags'))
+doc = '''Add elements classified on 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 the same length as `types'; each entry is a vector containing the tags (unique, strictly positive identifiers) of the elements of the corresponding type. `nodeTags' is also a vector of the same length as `types'; each entry is a vector of length equal to the number of elements of the given type times the number N of nodes per element, that contains the node tags of all the elements of the given type, concatenated: [e1n1, e1n2, ..., e1nN, e2n1, ...].'''
+mesh.add('addElements',doc,None,iint('dim'),iint('tag'),ivectorint('elementTypes'),ivectorvectorsize('elementTags'),ivectorvectorsize('nodeTags'))
 
-doc = '''Set the elements of type `elementType' in the entity of tag `tag'. `elementTags' contains the tags (unique, strictly positive identifiers) of the elements of the corresponding type. `nodeTags' is a vector of length equal to the number of elements times the number N of nodes per element, that contains the node tags of all the elements, concatenated: [e1n1, e1n2, ..., e1nN, e2n1, ...]. If the `elementTag' vector is empty, new tags are automatically assigned to the elements.'''
-mesh.add('setElementsByType',doc,None,iint('tag'),iint('elementType'),ivectorsize('elementTags'),ivectorsize('nodeTags'))
+doc = '''Add elements of type `elementType' classified on the entity of tag `tag'. `elementTags' contains the tags (unique, strictly positive identifiers) of the elements of the corresponding type. `nodeTags' is a vector of length equal to the number of elements times the number N of nodes per element, that contains the node tags of all the elements, concatenated: [e1n1, e1n2, ..., e1nN, e2n1, ...]. If the `elementTag' vector is empty, new tags are automatically assigned to the elements.'''
+mesh.add('addElementsByType',doc,None,iint('tag'),iint('elementType'),ivectorsize('elementTags'),ivectorsize('nodeTags'))
 
 doc = '''Get the numerical quadrature information for the given element type `elementType' and integration rule `integrationType' (e.g. "Gauss4" for a Gauss quadrature suited for integrating 4th order polynomials). `integrationPoints' contains the u, v, w coordinates of the G integration points in the reference element: [g1u, g1v, g1w, ..., gGu, gGv, gGw]. `integrationWeigths' contains the associated weights: [g1q, ..., gGq].'''
 mesh.add('getIntegrationPoints',doc,None,iint('elementType'),istring('integrationType'),ovectordouble('integrationPoints'),ovectordouble('integrationWeights'))
diff --git a/api/gmsh.h b/api/gmsh.h
index 08d3e18aaf..bd71fdd6e2 100644
--- a/api/gmsh.h
+++ b/api/gmsh.h
@@ -402,6 +402,9 @@ namespace gmsh { // Top-level functions
       // populated by the new 3D meshing algorithms.
       GMSH_API void getLastNodeError(std::vector<std::size_t> & nodeTags);
 
+      // Clear the mesh, i.e. delete all the nodes and elements.
+      GMSH_API void clear();
+
       // Get the nodes classified on the entity of dimension `dim' and tag `tag'.
       // If `tag' < 0, get the nodes for all entities of dimension `dim'. If `dim'
       // and `tag' are negative, get all the nodes in the mesh. `nodeTags' contains
@@ -454,8 +457,8 @@ namespace gmsh { // Top-level functions
                                              std::vector<std::size_t> & nodeTags,
                                              std::vector<double> & coord);
 
-      // Set the nodes classified on the model entity of dimension `dim' and tag
-      // `tag'. `nodeTags' contains the node tags (their unique, strictly positive
+      // Add nodes classified on the model entity of dimension `dim' and tag `tag'.
+      // `nodeTags' contains the node tags (their unique, strictly positive
       // identification numbers). `coord' is a vector of length 3 times the length
       // of `nodeTags' that contains the x, y, z coordinates of the nodes,
       // concatenated: [n1x, n1y, n1z, n2x, ...]. The optional `parametricCoord'
@@ -463,7 +466,7 @@ namespace gmsh { // Top-level functions
       // length of `parametricCoord' can be 0 or `dim' times the length of
       // `nodeTags'. If the `nodeTags' vector is empty, new tags are automatically
       // assigned to the nodes.
-      GMSH_API void setNodes(const int dim,
+      GMSH_API void addNodes(const int dim,
                              const int tag,
                              const std::vector<std::size_t> & nodeTags,
                              const std::vector<double> & coord,
@@ -581,30 +584,30 @@ namespace gmsh { // Top-level functions
                                               std::vector<std::size_t> & nodeTags,
                                               const int tag = -1);
 
-      // Set the 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 the same length
-      // as `types'; each entry is a vector containing the tags (unique, strictly
-      // positive identifiers) of the elements of the corresponding type.
-      // `nodeTags' is also a vector of the same length as `types'; each entry is a
-      // vector of length equal to the number of elements of the given type times
-      // the number N of nodes per element, that contains the node tags of all the
-      // elements of the given type, concatenated: [e1n1, e1n2, ..., e1nN, e2n1,
-      // ...].
-      GMSH_API void setElements(const int dim,
+      // Add elements classified on 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
+      // the same length as `types'; each entry is a vector containing the tags
+      // (unique, strictly positive identifiers) of the elements of the
+      // corresponding type. `nodeTags' is also a vector of the same length as
+      // `types'; each entry is a vector of length equal to the number of elements
+      // of the given type times the number N of nodes per element, that contains
+      // the node tags of all the elements of the given type, concatenated: [e1n1,
+      // e1n2, ..., e1nN, e2n1, ...].
+      GMSH_API void addElements(const int dim,
                                 const int tag,
                                 const std::vector<int> & elementTypes,
                                 const std::vector<std::vector<std::size_t> > & elementTags,
                                 const std::vector<std::vector<std::size_t> > & nodeTags);
 
-      // Set the elements of type `elementType' in the entity of tag `tag'.
+      // Add elements of type `elementType' classified on the entity of tag `tag'.
       // `elementTags' contains the tags (unique, strictly positive identifiers) of
       // the elements of the corresponding type. `nodeTags' is a vector of length
       // equal to the number of elements times the number N of nodes per element,
       // that contains the node tags of all the elements, concatenated: [e1n1,
       // e1n2, ..., e1nN, e2n1, ...]. If the `elementTag' vector is empty, new tags
       // are automatically assigned to the elements.
-      GMSH_API void setElementsByType(const int tag,
+      GMSH_API void addElementsByType(const int tag,
                                       const int elementType,
                                       const std::vector<std::size_t> & elementTags,
                                       const std::vector<std::size_t> & nodeTags);
diff --git a/api/gmsh.h_cwrap b/api/gmsh.h_cwrap
index b25ae741b6..f43a0ab2f2 100644
--- a/api/gmsh.h_cwrap
+++ b/api/gmsh.h_cwrap
@@ -800,6 +800,14 @@ namespace gmsh { // Top-level functions
         nodeTags.assign(api_nodeTags_, api_nodeTags_ + api_nodeTags_n_); gmshFree(api_nodeTags_);
       }
 
+      // Clear the mesh, i.e. delete all the nodes and elements.
+      inline void clear()
+      {
+        int ierr = 0;
+        gmshModelMeshClear(&ierr);
+        if(ierr) throw ierr;
+      }
+
       // Get the nodes classified on the entity of dimension `dim' and tag `tag'.
       // If `tag' < 0, get the nodes for all entities of dimension `dim'. If `dim'
       // and `tag' are negative, get all the nodes in the mesh. `nodeTags' contains
@@ -897,8 +905,8 @@ namespace gmsh { // Top-level functions
         coord.assign(api_coord_, api_coord_ + api_coord_n_); gmshFree(api_coord_);
       }
 
-      // Set the nodes classified on the model entity of dimension `dim' and tag
-      // `tag'. `nodeTags' contains the node tags (their unique, strictly positive
+      // Add nodes classified on the model entity of dimension `dim' and tag `tag'.
+      // `nodeTags' contains the node tags (their unique, strictly positive
       // identification numbers). `coord' is a vector of length 3 times the length
       // of `nodeTags' that contains the x, y, z coordinates of the nodes,
       // concatenated: [n1x, n1y, n1z, n2x, ...]. The optional `parametricCoord'
@@ -906,7 +914,7 @@ namespace gmsh { // Top-level functions
       // length of `parametricCoord' can be 0 or `dim' times the length of
       // `nodeTags'. If the `nodeTags' vector is empty, new tags are automatically
       // assigned to the nodes.
-      inline void setNodes(const int dim,
+      inline void addNodes(const int dim,
                            const int tag,
                            const std::vector<std::size_t> & nodeTags,
                            const std::vector<double> & coord,
@@ -916,7 +924,7 @@ namespace gmsh { // Top-level functions
         size_t *api_nodeTags_; size_t api_nodeTags_n_; vector2ptr(nodeTags, &api_nodeTags_, &api_nodeTags_n_);
         double *api_coord_; size_t api_coord_n_; vector2ptr(coord, &api_coord_, &api_coord_n_);
         double *api_parametricCoord_; size_t api_parametricCoord_n_; vector2ptr(parametricCoord, &api_parametricCoord_, &api_parametricCoord_n_);
-        gmshModelMeshSetNodes(dim, tag, api_nodeTags_, api_nodeTags_n_, api_coord_, api_coord_n_, api_parametricCoord_, api_parametricCoord_n_, &ierr);
+        gmshModelMeshAddNodes(dim, tag, api_nodeTags_, api_nodeTags_n_, api_coord_, api_coord_n_, api_parametricCoord_, api_parametricCoord_n_, &ierr);
         if(ierr) throw ierr;
         gmshFree(api_nodeTags_);
         gmshFree(api_coord_);
@@ -1110,17 +1118,17 @@ namespace gmsh { // Top-level functions
         nodeTags.assign(api_nodeTags_, api_nodeTags_ + api_nodeTags_n_); gmshFree(api_nodeTags_);
       }
 
-      // Set the 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 the same length
-      // as `types'; each entry is a vector containing the tags (unique, strictly
-      // positive identifiers) of the elements of the corresponding type.
-      // `nodeTags' is also a vector of the same length as `types'; each entry is a
-      // vector of length equal to the number of elements of the given type times
-      // the number N of nodes per element, that contains the node tags of all the
-      // elements of the given type, concatenated: [e1n1, e1n2, ..., e1nN, e2n1,
-      // ...].
-      inline void setElements(const int dim,
+      // Add elements classified on 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
+      // the same length as `types'; each entry is a vector containing the tags
+      // (unique, strictly positive identifiers) of the elements of the
+      // corresponding type. `nodeTags' is also a vector of the same length as
+      // `types'; each entry is a vector of length equal to the number of elements
+      // of the given type times the number N of nodes per element, that contains
+      // the node tags of all the elements of the given type, concatenated: [e1n1,
+      // e1n2, ..., e1nN, e2n1, ...].
+      inline void addElements(const int dim,
                               const int tag,
                               const std::vector<int> & elementTypes,
                               const std::vector<std::vector<std::size_t> > & elementTags,
@@ -1130,21 +1138,21 @@ namespace gmsh { // Top-level functions
         int *api_elementTypes_; size_t api_elementTypes_n_; vector2ptr(elementTypes, &api_elementTypes_, &api_elementTypes_n_);
         size_t **api_elementTags_; size_t *api_elementTags_n_, api_elementTags_nn_; vectorvector2ptrptr(elementTags, &api_elementTags_, &api_elementTags_n_, &api_elementTags_nn_);
         size_t **api_nodeTags_; size_t *api_nodeTags_n_, api_nodeTags_nn_; vectorvector2ptrptr(nodeTags, &api_nodeTags_, &api_nodeTags_n_, &api_nodeTags_nn_);
-        gmshModelMeshSetElements(dim, tag, api_elementTypes_, api_elementTypes_n_, (const size_t **)api_elementTags_, api_elementTags_n_, api_elementTags_nn_, (const size_t **)api_nodeTags_, api_nodeTags_n_, api_nodeTags_nn_, &ierr);
+        gmshModelMeshAddElements(dim, tag, api_elementTypes_, api_elementTypes_n_, (const size_t **)api_elementTags_, api_elementTags_n_, api_elementTags_nn_, (const size_t **)api_nodeTags_, api_nodeTags_n_, api_nodeTags_nn_, &ierr);
         if(ierr) throw ierr;
         gmshFree(api_elementTypes_);
         for(size_t i = 0; i < api_elementTags_nn_; ++i){ gmshFree(api_elementTags_[i]); } gmshFree(api_elementTags_); gmshFree(api_elementTags_n_);
         for(size_t i = 0; i < api_nodeTags_nn_; ++i){ gmshFree(api_nodeTags_[i]); } gmshFree(api_nodeTags_); gmshFree(api_nodeTags_n_);
       }
 
-      // Set the elements of type `elementType' in the entity of tag `tag'.
+      // Add elements of type `elementType' classified on the entity of tag `tag'.
       // `elementTags' contains the tags (unique, strictly positive identifiers) of
       // the elements of the corresponding type. `nodeTags' is a vector of length
       // equal to the number of elements times the number N of nodes per element,
       // that contains the node tags of all the elements, concatenated: [e1n1,
       // e1n2, ..., e1nN, e2n1, ...]. If the `elementTag' vector is empty, new tags
       // are automatically assigned to the elements.
-      inline void setElementsByType(const int tag,
+      inline void addElementsByType(const int tag,
                                     const int elementType,
                                     const std::vector<std::size_t> & elementTags,
                                     const std::vector<std::size_t> & nodeTags)
@@ -1152,7 +1160,7 @@ namespace gmsh { // Top-level functions
         int ierr = 0;
         size_t *api_elementTags_; size_t api_elementTags_n_; vector2ptr(elementTags, &api_elementTags_, &api_elementTags_n_);
         size_t *api_nodeTags_; size_t api_nodeTags_n_; vector2ptr(nodeTags, &api_nodeTags_, &api_nodeTags_n_);
-        gmshModelMeshSetElementsByType(tag, elementType, api_elementTags_, api_elementTags_n_, api_nodeTags_, api_nodeTags_n_, &ierr);
+        gmshModelMeshAddElementsByType(tag, elementType, api_elementTags_, api_elementTags_n_, api_nodeTags_, api_nodeTags_n_, &ierr);
         if(ierr) throw ierr;
         gmshFree(api_elementTags_);
         gmshFree(api_nodeTags_);
diff --git a/api/gmsh.jl b/api/gmsh.jl
index 77173803f4..c7ab9e4da8 100644
--- a/api/gmsh.jl
+++ b/api/gmsh.jl
@@ -1076,6 +1076,20 @@ function getLastNodeError()
     return nodeTags
 end
 
+"""
+    gmsh.model.mesh.clear()
+
+Clear the mesh, i.e. delete all the nodes and elements.
+"""
+function clear()
+    ierr = Ref{Cint}()
+    ccall((:gmshModelMeshClear, gmsh.lib), Cvoid,
+          (Ptr{Cint},),
+          ierr)
+    ierr[] != 0 && error("gmshModelMeshClear returned non-zero error code: $(ierr[])")
+    return nothing
+end
+
 """
     gmsh.model.mesh.getNodes(dim = -1, tag = -1, includeBoundary = false, returnParametricCoord = true)
 
@@ -1205,9 +1219,9 @@ function getNodesForPhysicalGroup(dim, tag)
 end
 
 """
-    gmsh.model.mesh.setNodes(dim, tag, nodeTags, coord, parametricCoord = Cdouble[])
+    gmsh.model.mesh.addNodes(dim, tag, nodeTags, coord, parametricCoord = Cdouble[])
 
-Set the nodes classified on the model entity of dimension `dim` and tag `tag`.
+Add nodes classified on the model entity of dimension `dim` and tag `tag`.
 `nodeTags` contains the node tags (their unique, strictly positive
 identification numbers). `coord` is a vector of length 3 times the length of
 `nodeTags` that contains the x, y, z coordinates of the nodes, concatenated:
@@ -1216,12 +1230,12 @@ parametric coordinates of the nodes, if any. The length of `parametricCoord` can
 be 0 or `dim` times the length of `nodeTags`. If the `nodeTags` vector is empty,
 new tags are automatically assigned to the nodes.
 """
-function setNodes(dim, tag, nodeTags, coord, parametricCoord = Cdouble[])
+function addNodes(dim, tag, nodeTags, coord, parametricCoord = Cdouble[])
     ierr = Ref{Cint}()
-    ccall((:gmshModelMeshSetNodes, gmsh.lib), Cvoid,
+    ccall((:gmshModelMeshAddNodes, gmsh.lib), Cvoid,
           (Cint, Cint, Ptr{Csize_t}, Csize_t, Ptr{Cdouble}, Csize_t, Ptr{Cdouble}, Csize_t, Ptr{Cint}),
           dim, tag, convert(Vector{Csize_t}, nodeTags), length(nodeTags), convert(Vector{Cdouble}, coord), length(coord), convert(Vector{Cdouble}, parametricCoord), length(parametricCoord), ierr)
-    ierr[] != 0 && error("gmshModelMeshSetNodes returned non-zero error code: $(ierr[])")
+    ierr[] != 0 && error("gmshModelMeshAddNodes returned non-zero error code: $(ierr[])")
     return nothing
 end
 
@@ -1452,9 +1466,9 @@ function getElementsByType(elementType, tag = -1, task = 0, numTasks = 1)
 end
 
 """
-    gmsh.model.mesh.setElements(dim, tag, elementTypes, elementTags, nodeTags)
+    gmsh.model.mesh.addElements(dim, tag, elementTypes, elementTags, nodeTags)
 
-Set the elements of the entity of dimension `dim` and tag `tag`. `types`
+Add elements classified on 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 the same length as `types`;
 each entry is a vector containing the tags (unique, strictly positive
@@ -1464,34 +1478,34 @@ the number of elements of the given type times the number N of nodes per
 element, that contains the node tags of all the elements of the given type,
 concatenated: [e1n1, e1n2, ..., e1nN, e2n1, ...].
 """
-function setElements(dim, tag, elementTypes, elementTags, nodeTags)
+function addElements(dim, tag, elementTypes, elementTags, nodeTags)
     api_elementTags_n_ = [ length(elementTags[i]) for i in 1:length(elementTags) ]
     api_nodeTags_n_ = [ length(nodeTags[i]) for i in 1:length(nodeTags) ]
     ierr = Ref{Cint}()
-    ccall((:gmshModelMeshSetElements, gmsh.lib), Cvoid,
+    ccall((:gmshModelMeshAddElements, gmsh.lib), Cvoid,
           (Cint, Cint, Ptr{Cint}, Csize_t, Ptr{Ptr{Csize_t}}, Ptr{Csize_t}, Csize_t, Ptr{Ptr{Csize_t}}, Ptr{Csize_t}, Csize_t, Ptr{Cint}),
           dim, tag, convert(Vector{Cint}, elementTypes), length(elementTypes), convert(Vector{Vector{Csize_t}},elementTags), api_elementTags_n_, length(elementTags), convert(Vector{Vector{Csize_t}},nodeTags), api_nodeTags_n_, length(nodeTags), ierr)
-    ierr[] != 0 && error("gmshModelMeshSetElements returned non-zero error code: $(ierr[])")
+    ierr[] != 0 && error("gmshModelMeshAddElements returned non-zero error code: $(ierr[])")
     return nothing
 end
 
 """
-    gmsh.model.mesh.setElementsByType(tag, elementType, elementTags, nodeTags)
+    gmsh.model.mesh.addElementsByType(tag, elementType, elementTags, nodeTags)
 
-Set the elements of type `elementType` in the entity of tag `tag`. `elementTags`
-contains the tags (unique, strictly positive identifiers) of the elements of the
-corresponding type. `nodeTags` is a vector of length equal to the number of
-elements times the number N of nodes per element, that contains the node tags of
-all the elements, concatenated: [e1n1, e1n2, ..., e1nN, e2n1, ...]. If the
-`elementTag` vector is empty, new tags are automatically assigned to the
-elements.
+Add elements of type `elementType` classified on the entity of tag `tag`.
+`elementTags` contains the tags (unique, strictly positive identifiers) of the
+elements of the corresponding type. `nodeTags` is a vector of length equal to
+the number of elements times the number N of nodes per element, that contains
+the node tags of all the elements, concatenated: [e1n1, e1n2, ..., e1nN, e2n1,
+...]. If the `elementTag` vector is empty, new tags are automatically assigned
+to the elements.
 """
-function setElementsByType(tag, elementType, elementTags, nodeTags)
+function addElementsByType(tag, elementType, elementTags, nodeTags)
     ierr = Ref{Cint}()
-    ccall((:gmshModelMeshSetElementsByType, gmsh.lib), Cvoid,
+    ccall((:gmshModelMeshAddElementsByType, gmsh.lib), Cvoid,
           (Cint, Cint, Ptr{Csize_t}, Csize_t, Ptr{Csize_t}, Csize_t, Ptr{Cint}),
           tag, elementType, convert(Vector{Csize_t}, elementTags), length(elementTags), convert(Vector{Csize_t}, nodeTags), length(nodeTags), ierr)
-    ierr[] != 0 && error("gmshModelMeshSetElementsByType returned non-zero error code: $(ierr[])")
+    ierr[] != 0 && error("gmshModelMeshAddElementsByType returned non-zero error code: $(ierr[])")
     return nothing
 end
 
diff --git a/api/gmsh.py b/api/gmsh.py
index 6c0a7dc38b..504db09bff 100644
--- a/api/gmsh.py
+++ b/api/gmsh.py
@@ -100,7 +100,7 @@ def _ovectorvectorint(ptr, size, n):
     return v
 
 def _ovectorvectorsize(ptr, size, n):
-    v = [_ovectorint(pointer(ptr[i].contents), size[i]) for i in range(n.value)]
+    v = [_ovectorsize(pointer(ptr[i].contents), size[i]) for i in range(n.value)]
     lib.gmshFree(size)
     lib.gmshFree(ptr)
     return v
@@ -1315,6 +1315,19 @@ class model:
                     ierr.value)
             return _ovectorsize(api_nodeTags_, api_nodeTags_n_.value)
 
+        @staticmethod
+        def clear():
+            """
+            Clear the mesh, i.e. delete all the nodes and elements.
+            """
+            ierr = c_int()
+            lib.gmshModelMeshClear(
+                byref(ierr))
+            if ierr.value != 0:
+                raise ValueError(
+                    "gmshModelMeshClear returned non-zero error code: ",
+                    ierr.value)
+
         @staticmethod
         def getNodes(dim=-1, tag=-1, includeBoundary=False, returnParametricCoord=True):
             """
@@ -1455,10 +1468,10 @@ class model:
                 _ovectordouble(api_coord_, api_coord_n_.value))
 
         @staticmethod
-        def setNodes(dim, tag, nodeTags, coord, parametricCoord=[]):
+        def addNodes(dim, tag, nodeTags, coord, parametricCoord=[]):
             """
-            Set the nodes classified on the model entity of dimension `dim' and tag
-            `tag'. `nodeTags' contains the node tags (their unique, strictly positive
+            Add nodes classified on the model entity of dimension `dim' and tag `tag'.
+            `nodeTags' contains the node tags (their unique, strictly positive
             identification numbers). `coord' is a vector of length 3 times the length
             of `nodeTags' that contains the x, y, z coordinates of the nodes,
             concatenated: [n1x, n1y, n1z, n2x, ...]. The optional `parametricCoord'
@@ -1471,7 +1484,7 @@ class model:
             api_coord_, api_coord_n_ = _ivectordouble(coord)
             api_parametricCoord_, api_parametricCoord_n_ = _ivectordouble(parametricCoord)
             ierr = c_int()
-            lib.gmshModelMeshSetNodes(
+            lib.gmshModelMeshAddNodes(
                 c_int(dim),
                 c_int(tag),
                 api_nodeTags_, api_nodeTags_n_,
@@ -1480,7 +1493,7 @@ class model:
                 byref(ierr))
             if ierr.value != 0:
                 raise ValueError(
-                    "gmshModelMeshSetNodes returned non-zero error code: ",
+                    "gmshModelMeshAddNodes returned non-zero error code: ",
                     ierr.value)
 
         @staticmethod
@@ -1743,23 +1756,24 @@ class model:
                 _ovectorsize(api_nodeTags_, api_nodeTags_n_.value))
 
         @staticmethod
-        def setElements(dim, tag, elementTypes, elementTags, nodeTags):
+        def addElements(dim, tag, elementTypes, elementTags, nodeTags):
             """
-            Set the 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 the same length as
-            `types'; each entry is a vector containing the tags (unique, strictly
-            positive identifiers) of the elements of the corresponding type. `nodeTags'
-            is also a vector of the same length as `types'; each entry is a vector of
-            length equal to the number of elements of the given type times the number N
-            of nodes per element, that contains the node tags of all the elements of
-            the given type, concatenated: [e1n1, e1n2, ..., e1nN, e2n1, ...].
+            Add elements classified on 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 the
+            same length as `types'; each entry is a vector containing the tags (unique,
+            strictly positive identifiers) of the elements of the corresponding type.
+            `nodeTags' is also a vector of the same length as `types'; each entry is a
+            vector of length equal to the number of elements of the given type times
+            the number N of nodes per element, that contains the node tags of all the
+            elements of the given type, concatenated: [e1n1, e1n2, ..., e1nN, e2n1,
+            ...].
             """
             api_elementTypes_, api_elementTypes_n_ = _ivectorint(elementTypes)
             api_elementTags_, api_elementTags_n_, api_elementTags_nn_ = _ivectorvectorsize(elementTags)
             api_nodeTags_, api_nodeTags_n_, api_nodeTags_nn_ = _ivectorvectorsize(nodeTags)
             ierr = c_int()
-            lib.gmshModelMeshSetElements(
+            lib.gmshModelMeshAddElements(
                 c_int(dim),
                 c_int(tag),
                 api_elementTypes_, api_elementTypes_n_,
@@ -1768,13 +1782,13 @@ class model:
                 byref(ierr))
             if ierr.value != 0:
                 raise ValueError(
-                    "gmshModelMeshSetElements returned non-zero error code: ",
+                    "gmshModelMeshAddElements returned non-zero error code: ",
                     ierr.value)
 
         @staticmethod
-        def setElementsByType(tag, elementType, elementTags, nodeTags):
+        def addElementsByType(tag, elementType, elementTags, nodeTags):
             """
-            Set the elements of type `elementType' in the entity of tag `tag'.
+            Add elements of type `elementType' classified on the entity of tag `tag'.
             `elementTags' contains the tags (unique, strictly positive identifiers) of
             the elements of the corresponding type. `nodeTags' is a vector of length
             equal to the number of elements times the number N of nodes per element,
@@ -1785,7 +1799,7 @@ class model:
             api_elementTags_, api_elementTags_n_ = _ivectorsize(elementTags)
             api_nodeTags_, api_nodeTags_n_ = _ivectorsize(nodeTags)
             ierr = c_int()
-            lib.gmshModelMeshSetElementsByType(
+            lib.gmshModelMeshAddElementsByType(
                 c_int(tag),
                 c_int(elementType),
                 api_elementTags_, api_elementTags_n_,
@@ -1793,7 +1807,7 @@ class model:
                 byref(ierr))
             if ierr.value != 0:
                 raise ValueError(
-                    "gmshModelMeshSetElementsByType returned non-zero error code: ",
+                    "gmshModelMeshAddElementsByType returned non-zero error code: ",
                     ierr.value)
 
         @staticmethod
diff --git a/api/gmshc.cpp b/api/gmshc.cpp
index 9c57463d00..0b30b9fcfe 100644
--- a/api/gmshc.cpp
+++ b/api/gmshc.cpp
@@ -778,6 +778,17 @@ GMSH_API void gmshModelMeshGetLastNodeError(size_t ** nodeTags, size_t * nodeTag
   }
 }
 
+GMSH_API void gmshModelMeshClear(int * ierr)
+{
+  if(ierr) *ierr = 0;
+  try {
+    gmsh::model::mesh::clear();
+  }
+  catch(int api_ierr_){
+    if(ierr) *ierr = api_ierr_;
+  }
+}
+
 GMSH_API void gmshModelMeshGetNodes(size_t ** nodeTags, size_t * nodeTags_n, double ** coord, size_t * coord_n, double ** parametricCoord, size_t * parametricCoord_n, const int dim, const int tag, const int includeBoundary, const int returnParametricCoord, int * ierr)
 {
   if(ierr) *ierr = 0;
@@ -853,14 +864,14 @@ GMSH_API void gmshModelMeshGetNodesForPhysicalGroup(const int dim, const int tag
   }
 }
 
-GMSH_API void gmshModelMeshSetNodes(const int dim, const int tag, size_t * nodeTags, size_t nodeTags_n, double * coord, size_t coord_n, double * parametricCoord, size_t parametricCoord_n, int * ierr)
+GMSH_API void gmshModelMeshAddNodes(const int dim, const int tag, size_t * nodeTags, size_t nodeTags_n, double * coord, size_t coord_n, double * parametricCoord, size_t parametricCoord_n, int * ierr)
 {
   if(ierr) *ierr = 0;
   try {
     std::vector<std::size_t> api_nodeTags_(nodeTags, nodeTags + nodeTags_n);
     std::vector<double> api_coord_(coord, coord + coord_n);
     std::vector<double> api_parametricCoord_(parametricCoord, parametricCoord + parametricCoord_n);
-    gmsh::model::mesh::setNodes(dim, tag, api_nodeTags_, api_coord_, api_parametricCoord_);
+    gmsh::model::mesh::addNodes(dim, tag, api_nodeTags_, api_coord_, api_parametricCoord_);
   }
   catch(int api_ierr_){
     if(ierr) *ierr = api_ierr_;
@@ -1003,7 +1014,7 @@ GMSH_API void gmshModelMeshPreallocateElementsByType(const int elementType, cons
   }
 }
 
-GMSH_API void gmshModelMeshSetElements(const int dim, const int tag, int * elementTypes, size_t elementTypes_n, const size_t ** elementTags, const size_t * elementTags_n, size_t elementTags_nn, const size_t ** nodeTags, const size_t * nodeTags_n, size_t nodeTags_nn, int * ierr)
+GMSH_API void gmshModelMeshAddElements(const int dim, const int tag, int * elementTypes, size_t elementTypes_n, const size_t ** elementTags, const size_t * elementTags_n, size_t elementTags_nn, const size_t ** nodeTags, const size_t * nodeTags_n, size_t nodeTags_nn, int * ierr)
 {
   if(ierr) *ierr = 0;
   try {
@@ -1014,20 +1025,20 @@ GMSH_API void gmshModelMeshSetElements(const int dim, const int tag, int * eleme
     std::vector<std::vector<std::size_t> > api_nodeTags_(nodeTags_nn);
     for(size_t i = 0; i < nodeTags_nn; ++i)
       api_nodeTags_[i] = std::vector<std::size_t>(nodeTags[i], nodeTags[i] + nodeTags_n[i]);
-    gmsh::model::mesh::setElements(dim, tag, api_elementTypes_, api_elementTags_, api_nodeTags_);
+    gmsh::model::mesh::addElements(dim, tag, api_elementTypes_, api_elementTags_, api_nodeTags_);
   }
   catch(int api_ierr_){
     if(ierr) *ierr = api_ierr_;
   }
 }
 
-GMSH_API void gmshModelMeshSetElementsByType(const int tag, const int elementType, size_t * elementTags, size_t elementTags_n, size_t * nodeTags, size_t nodeTags_n, int * ierr)
+GMSH_API void gmshModelMeshAddElementsByType(const int tag, const int elementType, size_t * elementTags, size_t elementTags_n, size_t * nodeTags, size_t nodeTags_n, int * ierr)
 {
   if(ierr) *ierr = 0;
   try {
     std::vector<std::size_t> api_elementTags_(elementTags, elementTags + elementTags_n);
     std::vector<std::size_t> api_nodeTags_(nodeTags, nodeTags + nodeTags_n);
-    gmsh::model::mesh::setElementsByType(tag, elementType, api_elementTags_, api_nodeTags_);
+    gmsh::model::mesh::addElementsByType(tag, elementType, api_elementTags_, api_nodeTags_);
   }
   catch(int api_ierr_){
     if(ierr) *ierr = api_ierr_;
diff --git a/api/gmshc.h b/api/gmshc.h
index e1105fd31f..31bc389c53 100644
--- a/api/gmshc.h
+++ b/api/gmshc.h
@@ -430,6 +430,9 @@ GMSH_API void gmshModelMeshGetLastEntityError(int ** dimTags, size_t * dimTags_n
 GMSH_API void gmshModelMeshGetLastNodeError(size_t ** nodeTags, size_t * nodeTags_n,
                                             int * ierr);
 
+/* Clear the mesh, i.e. delete all the nodes and elements. */
+GMSH_API void gmshModelMeshClear(int * ierr);
+
 /* Get the nodes classified on the entity of dimension `dim' and tag `tag'. If
  * `tag' < 0, get the nodes for all entities of dimension `dim'. If `dim' and
  * `tag' are negative, get all the nodes in the mesh. `nodeTags' contains the
@@ -487,8 +490,8 @@ GMSH_API void gmshModelMeshGetNodesForPhysicalGroup(const int dim,
                                                     double ** coord, size_t * coord_n,
                                                     int * ierr);
 
-/* Set the nodes classified on the model entity of dimension `dim' and tag
- * `tag'. `nodeTags' contains the node tags (their unique, strictly positive
+/* Add nodes classified on the model entity of dimension `dim' and tag `tag'.
+ * `nodeTags' contains the node tags (their unique, strictly positive
  * identification numbers). `coord' is a vector of length 3 times the length
  * of `nodeTags' that contains the x, y, z coordinates of the nodes,
  * concatenated: [n1x, n1y, n1z, n2x, ...]. The optional `parametricCoord'
@@ -496,7 +499,7 @@ GMSH_API void gmshModelMeshGetNodesForPhysicalGroup(const int dim,
  * of `parametricCoord' can be 0 or `dim' times the length of `nodeTags'. If
  * the `nodeTags' vector is empty, new tags are automatically assigned to the
  * nodes. */
-GMSH_API void gmshModelMeshSetNodes(const int dim,
+GMSH_API void gmshModelMeshAddNodes(const int dim,
                                     const int tag,
                                     size_t * nodeTags, size_t nodeTags_n,
                                     double * coord, size_t coord_n,
@@ -624,30 +627,31 @@ GMSH_API void gmshModelMeshPreallocateElementsByType(const int elementType,
                                                      const int tag,
                                                      int * ierr);
 
-/* Set the 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 the same length as
- * `types'; each entry is a vector containing the tags (unique, strictly
- * positive identifiers) of the elements of the corresponding type. `nodeTags'
- * is also a vector of the same length as `types'; each entry is a vector of
- * length equal to the number of elements of the given type times the number N
- * of nodes per element, that contains the node tags of all the elements of
- * the given type, concatenated: [e1n1, e1n2, ..., e1nN, e2n1, ...]. */
-GMSH_API void gmshModelMeshSetElements(const int dim,
+/* Add elements classified on 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 the
+ * same length as `types'; each entry is a vector containing the tags (unique,
+ * strictly positive identifiers) of the elements of the corresponding type.
+ * `nodeTags' is also a vector of the same length as `types'; each entry is a
+ * vector of length equal to the number of elements of the given type times
+ * the number N of nodes per element, that contains the node tags of all the
+ * elements of the given type, concatenated: [e1n1, e1n2, ..., e1nN, e2n1,
+ * ...]. */
+GMSH_API void gmshModelMeshAddElements(const int dim,
                                        const int tag,
                                        int * elementTypes, size_t elementTypes_n,
                                        const size_t ** elementTags, const size_t * elementTags_n, size_t elementTags_nn,
                                        const size_t ** nodeTags, const size_t * nodeTags_n, size_t nodeTags_nn,
                                        int * ierr);
 
-/* Set the elements of type `elementType' in the entity of tag `tag'.
+/* Add elements of type `elementType' classified on the entity of tag `tag'.
  * `elementTags' contains the tags (unique, strictly positive identifiers) of
  * the elements of the corresponding type. `nodeTags' is a vector of length
  * equal to the number of elements times the number N of nodes per element,
  * that contains the node tags of all the elements, concatenated: [e1n1, e1n2,
  * ..., e1nN, e2n1, ...]. If the `elementTag' vector is empty, new tags are
  * automatically assigned to the elements. */
-GMSH_API void gmshModelMeshSetElementsByType(const int tag,
+GMSH_API void gmshModelMeshAddElementsByType(const int tag,
                                              const int elementType,
                                              size_t * elementTags, size_t elementTags_n,
                                              size_t * nodeTags, size_t nodeTags_n,
diff --git a/demos/api/discrete.cpp b/demos/api/discrete.cpp
index 11d42b0bef..aa1eb949f2 100644
--- a/demos/api/discrete.cpp
+++ b/demos/api/discrete.cpp
@@ -11,7 +11,7 @@ int main(int argc, char **argv)
   gmsh::model::addDiscreteEntity(2, 1);
 
   // add 4 mesh nodes
-  gmsh::model::mesh::setNodes(2, 1,
+  gmsh::model::mesh::addNodes(2, 1,
                               {1, 2, 3, 4}, // node tags: 1, 2, 3, and 4
                               {0., 0., 0., // coordinates of node 1
                                1., 0., 0., // coordinates of node 2
@@ -19,7 +19,7 @@ int main(int argc, char **argv)
                                0., 1., 0.});
 
   // add 2 triangles
-  gmsh::model::mesh::setElements(2, 1,
+  gmsh::model::mesh::addElements(2, 1,
                                  {2}, // single type : 3-node triangle
                                  {{1, 2}}, // triangle tags: 1 and 2
                                  {{1, 2, 3, // triangle 1: nodes 1, 2, 3
diff --git a/demos/api/discrete.jl b/demos/api/discrete.jl
index 510db8db2e..463e561071 100644
--- a/demos/api/discrete.jl
+++ b/demos/api/discrete.jl
@@ -9,7 +9,7 @@ gmsh.model.add("test");
 gmsh.model.addDiscreteEntity(2, 1)
 
 # add 4 mesh nodes
-gmsh.model.mesh.setNodes(2, 1,
+gmsh.model.mesh.addNodes(2, 1,
                          [1, 2, 3, 4], # node tags: 1, 2, 3, and 4
                          [0., 0., 0., # coordinates of node 1
                           1., 0., 0., # coordinates of node 2
@@ -17,7 +17,7 @@ gmsh.model.mesh.setNodes(2, 1,
                           0., 1., 0.])
 
 # add 2 triangles
-gmsh.model.mesh.setElements(2, 1,
+gmsh.model.mesh.addElements(2, 1,
                             [2], # single type : 3-node triangle
                             [[1, 2]], # triangle tags: 1 and 2
                             [[1, 2, 3, # triangle 1: nodes 1, 2, 3
@@ -27,4 +27,3 @@ gmsh.model.mesh.setElements(2, 1,
 gmsh.write("test.msh")
 
 gmsh.finalize()
-
diff --git a/demos/api/discrete.py b/demos/api/discrete.py
index ddb353aaf8..0044b99885 100644
--- a/demos/api/discrete.py
+++ b/demos/api/discrete.py
@@ -10,7 +10,7 @@ gmsh.model.add("test");
 gmsh.model.addDiscreteEntity(2, 1)
 
 # add 4 mesh nodes
-gmsh.model.mesh.setNodes(2, 1,
+gmsh.model.mesh.addNodes(2, 1,
                          [1, 2, 3, 4], # node tags: 1, 2, 3, and 4
                          [0., 0., 0., # coordinates of node 1
                           1., 0., 0., # coordinates of node 2
@@ -18,7 +18,7 @@ gmsh.model.mesh.setNodes(2, 1,
                           0., 1., 0.])
 
 # add 2 triangles
-gmsh.model.mesh.setElements(2, 1,
+gmsh.model.mesh.addElements(2, 1,
                             [2], # single type : 3-node triangle
                             [[1, 2]], # triangle tags: 1 and 2
                             [[1, 2, 3, # triangle 1: nodes 1, 2, 3
@@ -28,4 +28,3 @@ gmsh.model.mesh.setElements(2, 1,
 gmsh.write("test.msh")
 
 gmsh.finalize()
-
diff --git a/demos/api/edges.cpp b/demos/api/edges.cpp
index 9cd4bf3672..24e421c568 100644
--- a/demos/api/edges.cpp
+++ b/demos/api/edges.cpp
@@ -65,7 +65,7 @@ int main(int argc, char **argv)
 
     // and add new 1D elements to it, for all edges
     int eleType1D = gmsh::model::mesh::getElementType("line", order);
-    gmsh::model::mesh::setElementsByType(c, eleType1D, {}, nodes);
+    gmsh::model::mesh::addElementsByType(c, eleType1D, {}, nodes);
 
     // this will create two 1D elements for each edge; to create unique elements
     // it would be useful to call getElementEdgeNodes() with the extra `primary'
diff --git a/demos/api/faces.cpp b/demos/api/faces.cpp
index ecf36324ea..fe3f5e1014 100644
--- a/demos/api/faces.cpp
+++ b/demos/api/faces.cpp
@@ -65,7 +65,7 @@ int main(int argc, char **argv)
 
     // and add new 2D elements to it, for all faces
     int eleType2D = gmsh::model::mesh::getElementType("triangle", order);
-    gmsh::model::mesh::setElementsByType(s, eleType2D, {}, nodes);
+    gmsh::model::mesh::addElementsByType(s, eleType2D, {}, nodes);
 
     // this will create two 2D elements for each face; to create unique elements
     // it would be useful to call getElementFaceNodes() with the extra `primary'
diff --git a/demos/api/mesh_from_discrete_curve.py b/demos/api/mesh_from_discrete_curve.py
index fa6c5cb3be..b3f3daed7a 100644
--- a/demos/api/mesh_from_discrete_curve.py
+++ b/demos/api/mesh_from_discrete_curve.py
@@ -13,10 +13,10 @@ N = 50
 dt = 2*math.pi/N
 pts = [[math.cos(i * dt), math.sin(i * dt), 0] for i in range(N)]
 flat_pts = [item for sublist in pts for item in sublist]
-gmsh.model.mesh.setNodes(1, 100, range(1, N+1), flat_pts)
+gmsh.model.mesh.addNodes(1, 100, range(1, N+1), flat_pts)
 n = [item for sublist in [[i, i+1] for i in range(1, N+1)] for item in sublist]
 n[-1] = 1
-gmsh.model.mesh.setElements(1, 100, [1], [range(1, N+1)], [n])
+gmsh.model.mesh.addElements(1, 100, [1], [range(1, N+1)], [n])
 
 # create a plane surface from the discrete curve
 gmsh.model.geo.addCurveLoop([100], 101)
diff --git a/demos/api/plugin.cpp b/demos/api/plugin.cpp
index 15c0286339..7d6c0c7f70 100644
--- a/demos/api/plugin.cpp
+++ b/demos/api/plugin.cpp
@@ -9,12 +9,12 @@ int main(int argc, char **argv)
   // Copied from discrete.cpp...
   gmsh::model::add("test");
   gmsh::model::addDiscreteEntity(2, 1);
-  gmsh::model::mesh::setNodes(2, 1, {1, 2, 3, 4},
+  gmsh::model::mesh::addNodes(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}},
+  gmsh::model::mesh::addElements(2, 1, {2}, {{1, 2}},
                                  {{1, 2, 3,
                                    1, 3, 4}});
   // ... end of copy
diff --git a/demos/api/plugin.py b/demos/api/plugin.py
index 5f735551fb..373792209e 100644
--- a/demos/api/plugin.py
+++ b/demos/api/plugin.py
@@ -7,12 +7,12 @@ gmsh.option.setNumber("General.Terminal", 1)
 # Copied from discrete.py...
 gmsh.model.add("test");
 gmsh.model.addDiscreteEntity(2, 1)
-gmsh.model.mesh.setNodes(2, 1, [1, 2, 3, 4],
+gmsh.model.mesh.addNodes(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]],
+gmsh.model.mesh.addElements(2, 1, [2], [[1, 2]],
                             [[1, 2, 3,
                               1, 3, 4]])
 # ... end of copy
diff --git a/demos/api/test.py b/demos/api/test.py
index 66b0d4bd77..a64951821d 100644
--- a/demos/api/test.py
+++ b/demos/api/test.py
@@ -48,7 +48,7 @@ for e in entities :
         print("tags : ", list(tags[i]))
         print("nodes : ", list(nodes[i]))
     if e[0] == [2] and e[1] == 6 :
-        model.mesh.setElements(e[0],e[1],types,[tags[0][:10]],[nodes[0][:30]])
+        model.mesh.addElements(e[0],e[1],types,[tags[0][:10]],[nodes[0][:30]])
 
 gmsh.write("mesh_truncated.msh")
 print("Nodes")
diff --git a/demos/api/view.cpp b/demos/api/view.cpp
index d65cf6e80f..4739dbe448 100644
--- a/demos/api/view.cpp
+++ b/demos/api/view.cpp
@@ -8,12 +8,12 @@ int main(int argc, char **argv)
   // Copied from discrete.cpp...
   gmsh::model::add("test");
   gmsh::model::addDiscreteEntity(2, 1);
-  gmsh::model::mesh::setNodes(2, 1, {1, 2, 3, 4},
+  gmsh::model::mesh::addNodes(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}},
+  gmsh::model::mesh::addElements(2, 1, {2}, {{1, 2}},
                                  {{1, 2, 3,
                                    1, 3, 4}});
   // ... end of copy
diff --git a/demos/api/view.py b/demos/api/view.py
index 881a8a66d0..6bb7a6b9c3 100644
--- a/demos/api/view.py
+++ b/demos/api/view.py
@@ -7,12 +7,12 @@ gmsh.option.setNumber("General.Terminal", 1)
 # Copied from discrete.py...
 gmsh.model.add("test");
 gmsh.model.addDiscreteEntity(2, 1)
-gmsh.model.mesh.setNodes(2, 1, [1, 2, 3, 4],
+gmsh.model.mesh.addNodes(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]],
+gmsh.model.mesh.addElements(2, 1, [2], [[1, 2]],
                             [[1, 2, 3,
                               1, 3, 4]])
 # ... end of copy
@@ -25,7 +25,7 @@ for step in range(0, 10):
     gmsh.view.addModelData(t, step, "test", "NodeData",
                            [1, 2, 3, 4], # tags of nodes
                            [[10.],[10.],[12.+step],[13.+step]]) # data, per node
-    
+
 gmsh.view.write(t, "data.msh")
-    
+
 gmsh.finalize()
diff --git a/doc/texinfo/api.texi b/doc/texinfo/api.texi
index f6bafb4d99..68b6ceee56 100644
--- a/doc/texinfo/api.texi
+++ b/doc/texinfo/api.texi
@@ -811,6 +811,18 @@ populated by the new 3D meshing algorithms.
 -
 @end table
 
+@item clear
+Clear the mesh, i.e. delete all the nodes and elements.
+
+@table @asis
+@item Input:
+-
+@item Output:
+-
+@item Return:
+-
+@end table
+
 @item getNodes
 Get the nodes classified on the entity of dimension @code{dim} and tag
 @code{tag}. If @code{tag} < 0, get the nodes for all entities of dimension
@@ -894,8 +906,8 @@ n2x, ...].
 -
 @end table
 
-@item setNodes
-Set the nodes classified on the model entity of dimension @code{dim} and tag
+@item addNodes
+Add nodes classified on the model entity of dimension @code{dim} and tag
 @code{tag}. @code{nodeTags} contains the node tags (their unique, strictly
 positive identification numbers). @code{coord} is a vector of length 3 times the
 length of @code{nodeTags} that contains the x, y, z coordinates of the nodes,
@@ -1081,16 +1093,17 @@ Preallocate data before calling @code{getElementsByType} with @code{numTasks} >
 -
 @end table
 
-@item setElements
-Set the elements of the entity of dimension @code{dim} and tag @code{tag}.
-@code{types} contains the MSH types of the elements (e.g. @code{2} for 3-node
-triangles: see the Gmsh reference manual). @code{elementTags} is a vector of the
-same length as @code{types}; each entry is a vector containing the tags (unique,
-strictly positive identifiers) of the elements of the corresponding type.
-@code{nodeTags} is also a vector of the same length as @code{types}; each entry
-is a vector of length equal to the number of elements of the given type times
-the number N of nodes per element, that contains the node tags of all the
-elements of the given type, concatenated: [e1n1, e1n2, ..., e1nN, e2n1, ...].
+@item addElements
+Add elements classified on the entity of dimension @code{dim} and tag
+@code{tag}. @code{types} contains the MSH types of the elements (e.g. @code{2}
+for 3-node triangles: see the Gmsh reference manual). @code{elementTags} is a
+vector of the same length as @code{types}; each entry is a vector containing the
+tags (unique, strictly positive identifiers) of the elements of the
+corresponding type. @code{nodeTags} is also a vector of the same length as
+@code{types}; each entry is a vector of length equal to the number of elements
+of the given type times the number N of nodes per element, that contains the
+node tags of all the elements of the given type, concatenated: [e1n1, e1n2, ...,
+e1nN, e2n1, ...].
 
 @table @asis
 @item Input:
@@ -1101,14 +1114,14 @@ elements of the given type, concatenated: [e1n1, e1n2, ..., e1nN, e2n1, ...].
 -
 @end table
 
-@item setElementsByType
-Set the elements of type @code{elementType} in the entity of tag @code{tag}.
-@code{elementTags} contains the tags (unique, strictly positive identifiers) of
-the elements of the corresponding type. @code{nodeTags} is a vector of length
-equal to the number of elements times the number N of nodes per element, that
-contains the node tags of all the elements, concatenated: [e1n1, e1n2, ...,
-e1nN, e2n1, ...]. If the @code{elementTag} vector is empty, new tags are
-automatically assigned to the elements.
+@item addElementsByType
+Add elements of type @code{elementType} classified on the entity of tag
+@code{tag}. @code{elementTags} contains the tags (unique, strictly positive
+identifiers) of the elements of the corresponding type. @code{nodeTags} is a
+vector of length equal to the number of elements times the number N of nodes per
+element, that contains the node tags of all the elements, concatenated: [e1n1,
+e1n2, ..., e1nN, e2n1, ...]. If the @code{elementTag} vector is empty, new tags
+are automatically assigned to the elements.
 
 @table @asis
 @item Input:
-- 
GitLab