diff --git a/.gitignore b/.gitignore
index 11b72be90316ce3f846b8c32c93788d186cb09ed..154f2216bd638449b5d565e869a72b70937c0314 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
 bin*/
 lib*/
 build*/
+install/
 contrib/mobile/frameworks_*
 contrib/3M
 contrib/Parasolid
@@ -11,8 +12,12 @@ doc/doxygen/html
 *~
 *.so
 *.so.*
+*.mod
 *#
 *.pyc
 ## CLion directories
 .idea
 cmake-build-*
+
+# VS Code directories
+.vscode/
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 86389b0dbfec8ed2e973d143dfff57c6a52f86cb..5de25e1fc9ca0bd324c90ee0955987cd2f936b4e 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -1,6 +1,7 @@
-4.11.0 (Work-in-progress): improved copying ("Duplicata") of multiple shapes
-with OCC; reduced default order for OCC surface filling; arbitrary string
-attributes can now be stored in models and MSH files; small bug fixes.
+4.11.0 (Work-in-progress): new Fortran API; improved copying ("Duplicata") of
+multiple shapes with OCC; reduced default order for OCC surface filling;
+arbitrary string attributes can now be stored in models and MSH files; small bug
+fixes.
 
 * New API functions: model/getAttributeNames, model/getAttribute,
   model/setAttribute, model/removeAttribute
diff --git a/CMakeLists.txt b/CMakeLists.txt
index dc60ac149ac765decab20acc8f20d0e3c6fe445d..b75bd95a77f6d0dc70b6ce1cd2731b3e3825ca82 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -142,7 +142,7 @@ else()
   set(GMSH_GITLAB_PREFIX "${GMSH_GITLAB_PREFIX}/blob/master")
 endif()
 
-set(GMSH_API api/gmsh.h api/gmshc.h api/gmsh.h_cwrap api/gmshf.h)
+set(GMSH_API api/gmsh.h api/gmshc.h api/gmsh.h_cwrap api/gmsh.f90)
 
 if(ENABLE_PRIVATE_API)
   message(WARNING "The private API is unsupported and undocumented. It is meant "
@@ -1812,6 +1812,7 @@ file(GLOB TUTORIALS_CPP_FILES ${CMAKE_CURRENT_SOURCE_DIR}/tutorials/c++/?*.*)
 file(GLOB TUTORIALS_C_FILES ${CMAKE_CURRENT_SOURCE_DIR}/tutorials/c/?*.*)
 file(GLOB TUTORIALS_PY_FILES ${CMAKE_CURRENT_SOURCE_DIR}/tutorials/python/?*.*)
 file(GLOB TUTORIALS_JL_FILES ${CMAKE_CURRENT_SOURCE_DIR}/tutorials/julia/?*.*)
+file(GLOB TUTORIALS_F90_FILES ${CMAKE_CURRENT_SOURCE_DIR}/tutorials/fortran/?*.*)
 file(GLOB EXAMPLES ${CMAKE_CURRENT_SOURCE_DIR}/examples/*)
 foreach(SUBDIR ${EXAMPLES})
   if(IS_DIRECTORY ${SUBDIR})
@@ -1872,6 +1873,7 @@ if(WIN32)
     unix2dos(TUTORIALS_C_FILES "c")
     unix2dos(TUTORIALS_PY_FILES "python")
     unix2dos(TUTORIALS_JL_FILES "julia")
+    unix2dos(TUTORIALS_F90_FILES "fortran")
     foreach(DIR ${EXAMPLES_DIRS})
       file(GLOB EXAMPLES_FILES ${DIR}/?*.*)
       unix2dos(EXAMPLES_FILES "examples")
@@ -1933,6 +1935,7 @@ install(FILES ${TUTORIALS_CPP_FILES} DESTINATION ${GMSH_DOC}/tutorials/c++)
 install(FILES ${TUTORIALS_C_FILES} DESTINATION ${GMSH_DOC}/tutorials/c)
 install(FILES ${TUTORIALS_PY_FILES} DESTINATION ${GMSH_DOC}/tutorials/python)
 install(FILES ${TUTORIALS_JL_FILES} DESTINATION ${GMSH_DOC}/tutorials/julia)
+install(FILES ${TUTORIALS_F90_FILES} DESTINATION ${GMSH_DOC}/tutorials/fortran)
 foreach(DIR ${EXAMPLES_DIRS})
   get_filename_component(EXAMPLES_DIR_NAME ${DIR} NAME)
   file(GLOB EXAMPLES_FILES ${DIR}/?*.*)
diff --git a/CREDITS.txt b/CREDITS.txt
index c3883ef9ccc393f8d14192c74dac35d31dcab743..d5814536b6dd676cc925940d80874c1da74f84d3 100644
--- a/CREDITS.txt
+++ b/CREDITS.txt
@@ -33,8 +33,9 @@ Badia (hierarchical basis functions), Jeremy Theler (X3D export), Thomas
 Toulorge (high order mesh optimizer, new CGNS IO), Max Orok (binary PLY), Marek
 Wojciechowski (PyPi packaging), Maxence Reberol (automatic transfinite, quad
 meshing tools), Michael Ermakov (Gambit export, Fortran API, TransfiniteTri),
-Alex Krasner (X3D export). See comments in the sources for more information. If
-we forgot to list your contributions please send us an email!
+Alex Krasner (X3D export), Giannis Nikiteas (Fortran API). See comments in the
+sources for more information. If we forgot to list your contributions please
+send us an email!
 
 Thanks to the following folks who have contributed by providing fresh ideas on
 theoretical or programming topics, who have sent patches, requests for changes
diff --git a/README.txt b/README.txt
index 3751ceabde5e11dfbc372469e55f9c2111e1a6b9..77ba8bf3ac34c1841672ffde692684af58c1b512 100644
--- a/README.txt
+++ b/README.txt
@@ -44,8 +44,8 @@ Build Gmsh from the command line
   CMAKE_INSTALL_PREFIX - see below).
 
 * To build the Gmsh app dynamically linked to the shared Gmsh library, which can
-  then also be used by external codes through the C++, C, Python and Julia Gmsh
-  API, run
+  then also be used by external codes through the C++, C, Python, Julia and
+  Fortran Gmsh API, run
 
     cd build
     cmake -DENABLE_BUILD_DYNAMIC=1 ..
@@ -53,7 +53,7 @@ Build Gmsh from the command line
     make install
 
   This will install the Gmsh app and the shared Gmsh library, as well as the C++
-  and C include files and the Python and Julia modules.
+  and C include files, and the Python, Julia and Fortran modules.
 
 * To change build options you can use "ccmake" instead of "cmake", e.g.:
 
diff --git a/api/GenApi.py b/api/GenApi.py
index 93b0eb2b64654b27ec326d5c92b5001ea78eba8a..955f7ec8f63e8900f08f73ab6ae39b7be80e9b3e 100644
--- a/api/GenApi.py
+++ b/api/GenApi.py
@@ -4,14 +4,15 @@
 # Please report all issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
 
 # Contributor(s):
-#   Jonathan Lambrechts
+#   Jonathan Lambrechts, Giannis Nikiteas
 
 import textwrap
 import string
 import os
 import re
 
-
+# TODO: Fortran mark all output variables with intent(out)
+# TODO: Fortran all methods that return a single value, should be functions not subroutines
 class arg:
     def __init__(self, name, value, python_value, julia_value, cpp_type,
                  c_type, out):
@@ -36,9 +37,12 @@ class arg:
         self.julia_pre = ""
         self.julia_post = ""
         self.julia_return = name
-        self.fortran_type_post = ""
-        self.fortran_name_pre  = ""
-        self.fortran_name_post = ""
+        self.fortran_args = [name]
+        self.fortran_c_args = [name]
+        self.fortran_pre = None
+        self.fortran_post = None
+        self.fortran_call = None
+        self.fortran_local = None
         self.texi = name + (
             (" = " + self.python_value) if self.python_value else "")
 
@@ -52,7 +56,9 @@ def ibool(name, value=None, python_value=None, julia_value=None):
     a.python_arg = "c_int(bool(" + name + "))"
     a.cwrap_arg = "(int)" + name
     a.julia_ctype = "Cint"
-    a.fortran_type = "integer(c_int), value"
+    a.fortran_types = ["logical, intent(in)"]
+    a.fortran_c_api = ["integer(c_int), value, intent(in)"]
+    a.fortran_call = f"{name}=optval_c_bool(.{value}., {name})" if value is not None else f"{name}=merge(1_c_int, 0_c_int, {name})"
     return a
 
 
@@ -61,7 +67,9 @@ def iint(name, value=None, python_value=None, julia_value=None):
             False)
     a.python_arg = "c_int(" + name + ")"
     a.julia_ctype = "Cint"
-    a.fortran_type = "integer(c_int), value"
+    a.fortran_types = ["integer, intent(in)"]
+    a.fortran_c_api = ["integer(c_int), value, intent(in)"]
+    a.fortran_call = f"{name}=optval_c_int({value}, {name})" if value is not None else f"{name}=int({name}, c_int)"
     return a
 
 
@@ -70,7 +78,9 @@ def isize(name, value=None, python_value=None, julia_value=None):
             "const size_t", False)
     a.python_arg = "c_size_t(" + name + ")"
     a.julia_ctype = "Csize_t"
-    a.fortran_type = "integer(c_size_t), value"
+    a.fortran_types = ["integer, intent(in)"]
+    a.fortran_c_api = ["integer(c_size_t), value, intent(in)"]
+    a.fortran_call = f"{name}=optval_c_size_t({value}, {name})" if value is not None else f"{name}=int({name}, c_size_t)"
     return a
 
 
@@ -79,7 +89,9 @@ def idouble(name, value=None, python_value=None, julia_value=None):
             "const double", False)
     a.python_arg = "c_double(" + name + ")"
     a.julia_ctype = "Cdouble"
-    a.fortran_type = "real(c_double), value"
+    a.fortran_types = ["real(c_double), intent(in)"]
+    a.fortran_c_api = ["real(c_double), value, intent(in)"]
+    a.fortran_call = f"{name}=optval_c_double({value}, {name})" if value is not None else f"{name}=real({name}, c_double)"
     return a
 
 
@@ -89,8 +101,9 @@ def istring(name, value=None, python_value=None, julia_value=None):
     a.python_arg = "c_char_p(" + name + ".encode())"
     a.cwrap_arg = name + ".c_str()"
     a.julia_ctype = "Ptr{Cchar}"
-    a.fortran_type = "character(len = 1, kind = c_char)"
-    a.fortran_type_post = "(*)"
+    a.fortran_types = ["character(len=*), intent(in)"]
+    a.fortran_c_api = ["character(len=1, kind=c_char), dimension(*), intent(in)"]
+    a.fortran_call = f"{name}=istring_(optval_c_str({value}, {name}))" if value is not None else f"{name}=istring_({name})"
     return a
 
 
@@ -99,8 +112,8 @@ def ivoidstar(name, value=None, python_value=None, julia_value=None):
             "const void *", False)
     a.python_arg = "c_void_p(" + name + ")"
     a.julia_ctype = "Ptr{Cvoid}"
-    a.fortran_type = "integer(c_int)"
-    a.fortran_type_post = "(*)"
+    a.fortran_types = ["type(c_ptr), intent(in)"]
+    a.fortran_c_api = ["type(c_ptr), value, intent(in)"]
     return a
 
 
@@ -124,9 +137,11 @@ def ivectorint(name, value=None, python_value=None, julia_value=None):
     a.python_arg = api_name + ", " + api_name_n
     a.julia_ctype = "Ptr{Cint}, Csize_t"
     a.julia_arg = "convert(Vector{Cint}, " + name + "), length(" + name + ")"
-    a.fortran_type = "integer(c_int)"
-    a.fortran_type_post = "(*)\n            integer(c_size_t), value :: " + name + "_n"
-    a.fortran_name_post = ",\n     &      " + name + "_n"
+    a.fortran_args = [name]
+    a.fortran_types = ["integer(c_int), dimension(:), intent(in)"]
+    a.fortran_c_api = ["integer(c_int), dimension(*)", "integer(c_size_t), value, intent(in)"]
+    a.fortran_c_args = [api_name, api_name_n]
+    a.fortran_call = f"{api_name}={name}, &{api_name_n}=size_gmsh_int({name})"
     return a
 
 
@@ -150,9 +165,11 @@ def ivectorsize(name, value=None, python_value=None, julia_value=None):
     a.python_arg = api_name + ", " + api_name_n
     a.julia_ctype = "Ptr{Csize_t}, Csize_t"
     a.julia_arg = "convert(Vector{Csize_t}, " + name + "), length(" + name + ")"
-    a.fortran_type = "integer(c_size_t)"
-    a.fortran_type_post = "(*)\n            integer(c_size_t), value :: " + name + "_n"
-    a.fortran_name_post = ",\n     &      " + name + "_n"
+    a.fortran_args = [name]
+    a.fortran_types = ["integer(c_size_t), dimension(:), intent(in)"]
+    a.fortran_c_api = ["integer(c_size_t), dimension(*)", "integer(c_size_t), value, intent(in)"]
+    a.fortran_c_args = [api_name, api_name_n]
+    a.fortran_call = f"{api_name}={name}, &{api_name_n}=size_gmsh_size({name})"
     return a
 
 
@@ -176,9 +193,11 @@ def ivectordouble(name, value=None, python_value=None, julia_value=None):
     a.python_arg = api_name + ", " + api_name_n
     a.julia_ctype = "Ptr{Cdouble}, Csize_t"
     a.julia_arg = "convert(Vector{Cdouble}, " + name + "), length(" + name + ")"
-    a.fortran_type = "real(c_double)"
-    a.fortran_type_post = "(*)\n            integer(c_size_t), value :: " + name + "_n"
-    a.fortran_name_post = ",\n     &      " + name + "_n"
+    a.fortran_args = [name]
+    a.fortran_types = ["real(c_double), dimension(:), intent(in)"]
+    a.fortran_c_api = ["real(c_double), dimension(*)", "integer(c_size_t), value, intent(in)"]
+    a.fortran_c_args = [api_name, api_name_n]
+    a.fortran_call = f"{api_name}={name}, &{api_name_n}=size_gmsh_double({name})"
     return a
 
 
@@ -202,9 +221,15 @@ def ivectorstring(name, value=None, python_value=None, julia_value=None):
     a.python_arg = api_name + ", " + api_name_n
     a.julia_ctype = "Ptr{Ptr{Cchar}}, Csize_t"
     a.julia_arg = name + ", length(" + name + ")"
-    a.fortran_type = "type(c_ptr)"
-    a.fortran_type_post = "(*)\n            integer(c_size_t), value :: " + name + "_n"
-    a.fortran_name_post = ",\n     &      " + name + "_n"
+    a.fortran_args = [name]
+    a.fortran_types = ["character(len=*), dimension(:), intent(in)"]
+    a.fortran_c_api = ["type(c_ptr), dimension(*)", "integer(c_size_t), value, intent(in)"]
+    a.fortran_c_args = [api_name, api_name_n]
+    # pass the locally created api_name variable to the C interface
+    a.fortran_call = f"{api_name}={api_name}, &{api_name_n}=size_gmsh_str({name})"
+    a.fortran_pre = f"call ivectorstring_({name}, &{api_name}strs, &{api_name})"
+    a.fortran_local = [f"character(len=GMSH_API_MAX_STR_LEN, kind=c_char), allocatable :: {api_name}strs(:)",
+                       f"type(c_ptr), allocatable :: {api_name}(:)"]
     return a
 
 
@@ -233,9 +258,11 @@ def ivectorpair(name, value=None, python_value=None, julia_value=None):
     a.julia_pre = (api_name + " = collect(Cint, Iterators.flatten(" + name +
                    "))\n    " + api_name_n + " = length(" + api_name + ")")
     a.julia_arg = (api_name + ", " + api_name_n)
-    a.fortran_type = "integer(c_int)"
-    a.fortran_type_post = "(*)\n            integer(c_size_t), value :: " + name + "_n"
-    a.fortran_name_post = ",\n     &      " + name + "_n"
+    a.fortran_args = [name]
+    a.fortran_types = ["integer(c_int), dimension(:,:), intent(in)"]
+    a.fortran_c_api = ["integer(c_int), dimension(*)", "integer(c_size_t), value, intent(in)"]
+    a.fortran_c_args = [api_name, api_name_n]
+    a.fortran_call = f"{api_name}={name}, &{api_name_n}=size_gmsh_pair({name})"
     return a
 
 
@@ -271,10 +298,13 @@ def ivectorvectorint(name, value=None, python_value=None, julia_value=None):
                    "[i]) for i in 1:length(" + name + ") ]")
     a.julia_arg = ("convert(Vector{Vector{Cint}}," + name + "), " +
                    api_name_n + ", length(" + name + ")")
-    a.fortran_type = "type(c_ptr), intent(out)"
-    a.fortran_type_post = ("\n            type(c_ptr), intent(out) :: " + name +
-                           "_n\n            integer(c_size_t) :: " + name + "_nn")
-    a.fortran_name_post = ",\n     &      " + name + "_n,\n     &      "  + name + "_nn"
+    a.fortran_args = [name, name + "_n"]
+    a.fortran_types = ["integer(c_int), dimension(:), intent(in)", "integer(c_size_t), dimension(:), intent(in)"]
+    a.fortran_c_api = ["type(c_ptr), intent(in)", "type(c_ptr), intent(in)", "integer(c_size_t), value, intent(in)"]
+    a.fortran_c_args = [api_name, api_name_n, api_name_nn]
+    a.fortran_pre = f"call ivectorvectorint_({name}, &{name}_n, &{api_name}, &{api_name_n}, &{api_name_nn})"
+    a.fortran_local = [f"type(c_ptr) :: {api_name}", f"type(c_ptr) :: {api_name_n}", f"integer(c_size_t) :: {api_name_nn}"]
+    a.fortran_call = f"{api_name}={api_name}, &{api_name_n}={api_name_n}, &{api_name_nn}={api_name_nn}"
     return a
 
 
@@ -311,10 +341,13 @@ def ivectorvectorsize(name, value=None, python_value=None, julia_value=None):
                    "[i]) for i in 1:length(" + name + ") ]")
     a.julia_arg = ("convert(Vector{Vector{Csize_t}}," + name + "), " +
                    api_name_n + ", length(" + name + ")")
-    a.fortran_type = "type(c_ptr), intent(out)"
-    a.fortran_type_post = ("\n            type(c_ptr), intent(out) :: " + name +
-                           "_n\n            integer(c_size_t) :: " + name + "_nn")
-    a.fortran_name_post = ",\n     &      " + name + "_n,\n     &      "  + name + "_nn"
+    a.fortran_args = [name, name + "_n"]
+    a.fortran_types = ["integer(c_size_t), dimension(:), intent(in)", "integer(c_size_t), dimension(:), intent(in)"]
+    a.fortran_c_api = ["type(c_ptr), intent(in)", "type(c_ptr), intent(in)", "integer(c_size_t), value, intent(in)"]
+    a.fortran_c_args = [api_name, api_name_n, api_name_nn]
+    a.fortran_pre = f"call ivectorvectorsize_({name}, &{name}_n, &{api_name}, &{api_name_n}, &{api_name_nn})"
+    a.fortran_local = [f"type(c_ptr) :: {api_name}", f"type(c_ptr) :: {api_name_n}", f"integer(c_size_t) :: {api_name_nn}"]
+    a.fortran_call = f"{api_name}={api_name}, &{api_name_n}={api_name_n}, &{api_name_nn}={api_name_nn}"
     return a
 
 
@@ -351,23 +384,25 @@ def ivectorvectordouble(name, value=None, python_value=None, julia_value=None):
                    "[i]) for i in 1:length(" + name + ") ]")
     a.julia_arg = ("convert(Vector{Vector{Cdouble}}," + name + "), " +
                    api_name_n + ", length(" + name + ")")
-    a.fortran_type = "type(c_ptr), intent(out)"
-    a.fortran_type_post = ("\n            type(c_ptr), intent(out) :: " +
-                           name + "_n\n            integer(c_size_t) :: " + name + "_nn")
-    a.fortran_name_post = ",\n     &      " + name + "_n,\n     &      "  + name + "_nn"
+    a.fortran_args = [name, name + "_n"]
+    a.fortran_types = ["real(c_double), dimension(:), intent(in)", "integer(c_size_t), dimension(:), intent(in)"]
+    a.fortran_c_api = ["type(c_ptr), intent(in)", "type(c_ptr), intent(in)", "integer(c_size_t), value, intent(in)"]
+    a.fortran_c_args = [api_name, api_name_n, api_name_nn]
+    a.fortran_pre = f"call ivectorvectordouble_({name}, &{name}_n, &{api_name}, &{api_name_n}, &{api_name_nn})"
+    a.fortran_local = [f"type(c_ptr) :: {api_name}", f"type(c_ptr) :: {api_name_n}", f"integer(c_size_t) :: {api_name_nn}"]
+    a.fortran_call = f"{api_name}={api_name}, &{api_name_n}={api_name_n}, &{api_name_nn}={api_name_nn}"
     return a
 
 
 # output types
 
-
 class oint(arg):
     rcpp_type = "int"
     rc_type = "int"
     rtexi_type = "integer value"
     rjulia_type = "Cint"
-    fortran_type = "integer(c_int)"
-    fortran_type_post = ""
+    fortran_c_api = ["integer(c_int)"]
+    fortran_types = ["integer(c_int)"]
 
     def __init__(self, name, value=None, python_value=None, julia_value=None):
         arg.__init__(self, name, value, python_value, julia_value, "int &",
@@ -389,8 +424,8 @@ class osize(arg):
     rc_type = "size_t"
     rtexi_type = "size value"
     rjulia_type = "Csize_t"
-    fortran_type = "integer(c_size_t)"
-    fortran_type_post = ""
+    fortran_c_api = ["integer(c_size_t)"]
+    fortran_types = ["integer(c_size_t)"]
 
     def __init__(self, name, value=None, python_value=None, julia_value=None):
         arg.__init__(self, name, value, python_value, julia_value,
@@ -412,8 +447,8 @@ class odouble(arg):
     rc_type = "double"
     rtexi_type = "floating point value"
     rjulia_type = "Cdouble"
-    fortran_type = "real(c_double)"
-    fortran_type_post = ""
+    fortran_c_api = ["real(c_double)"]
+    fortran_types = ["real(c_double)"]
 
     def __init__(self, name, value=None, python_value=None, julia_value=None):
         arg.__init__(self, name, value, python_value, julia_value, "double &",
@@ -448,8 +483,11 @@ def ostring(name, value=None, python_value=None, julia_value=None):
     a.julia_pre = api_name + " = Ref{Ptr{Cchar}}()"
     a.julia_arg = api_name
     a.julia_post = name + " = unsafe_string(" + api_name + "[])"
-    a.fortran_type = "type(c_ptr)"
-    a.fortran_type_post = "(*)"
+    a.fortran_args = [name]
+    a.fortran_types = ["character(len=:), allocatable, intent(out)"]
+    a.fortran_c_api = ["character(kind=c_char), dimension(*)"]
+    a.fortran_c_args = [api_name]
+    # TODO: Does this need to be C deallocated?
     return a
 
 
@@ -475,9 +513,13 @@ def ovectorint(name, value=None, python_value=None, julia_value=None):
     a.julia_arg = api_name + ", " + api_name_n
     a.julia_post = (name + " = unsafe_wrap(Array, " + api_name + "[], " +
                     api_name_n + "[], own = true)")
-    a.fortran_type = "type(c_ptr), intent(out)"
-    a.fortran_type_post = "\n            integer(c_size_t) :: " + name +"_n"
-    a.fortran_name_post = ",\n     &      " + name + "_n"
+    a.fortran_args = [name]
+    a.fortran_types = ["integer(c_int), dimension(:), allocatable, intent(out)"]
+    a.fortran_c_api = ["type(c_ptr), intent(out)", "integer(c_size_t), intent(out)"]
+    a.fortran_c_args = [api_name, api_name_n]
+    a.fortran_call = f"{api_name}={api_name}, &{api_name_n}={api_name_n}"
+    a.fortran_post = f"{name} = ovectorint_({api_name}, &{api_name_n})"
+    a.fortran_local = [f"type(c_ptr) :: {api_name}", f"integer(c_size_t) :: {api_name_n}"]
     return a
 
 
@@ -503,9 +545,13 @@ def ovectorsize(name, value=None, python_value=None, julia_value=None):
     a.julia_arg = api_name + ", " + api_name_n
     a.julia_post = (name + " = unsafe_wrap(Array, " + api_name + "[], " +
                     api_name_n + "[], own = true)")
-    a.fortran_type = "type(c_ptr), intent(out)"
-    a.fortran_type_post = "\n            integer(c_size_t) :: " + name + "_n"
-    a.fortran_name_post = ",\n     &      " + name + "_n"
+    a.fortran_args = [name]
+    a.fortran_types = ["integer(c_size_t), dimension(:), allocatable, intent(out)"]
+    a.fortran_c_api = ["type(c_ptr), intent(out)", "integer(c_size_t), intent(out)"]
+    a.fortran_c_args = [api_name, api_name_n]
+    a.fortran_call = f"{api_name}={api_name}, &{api_name_n}={api_name_n}"
+    a.fortran_post = f"{name} = ovectorsize_({api_name}, &{api_name_n})"
+    a.fortran_local = [f"type(c_ptr) :: {api_name}", f"integer(c_size_t) :: {api_name_n}"]
     return a
 
 
@@ -531,9 +577,13 @@ def ovectordouble(name, value=None, python_value=None, julia_value=None):
     a.julia_arg = api_name + ", " + api_name_n
     a.julia_post = (name + " = unsafe_wrap(Array, " + api_name + "[], " +
                     api_name_n + "[], own = true)")
-    a.fortran_type = "type(c_ptr), intent(out)"
-    a.fortran_type_post = "\n            integer(c_size_t) :: " + name + "_n"
-    a.fortran_name_post = ",\n     &      " + name + "_n"
+    a.fortran_args = [name]
+    a.fortran_c_api = ["type(c_ptr), intent(out)", "integer(c_size_t)"]
+    a.fortran_c_args = [api_name, api_name_n]
+    a.fortran_types = ["real(c_double), dimension(:), allocatable, intent(out)"]
+    a.fortran_call = f"{api_name}={api_name}, &{api_name_n}={api_name_n}"
+    a.fortran_post = f"{name} = ovectordouble_({api_name}, &{api_name_n})"
+    a.fortran_local = [f"type(c_ptr) :: {api_name}", f"integer(c_size_t) :: {api_name_n}"]
     return a
 
 
@@ -564,9 +614,13 @@ def ovectorstring(name, value=None, python_value=None, julia_value=None):
                     "[], " + api_name_n + "[], own = true)\n    " + name +
                     " = [unsafe_string(tmp_" + api_name +
                     "[i]) for i in 1:length(tmp_" + api_name + ") ]")
-    a.fortran_type = "type(c_ptr), intent(out)"
-    a.fortran_type_post = "\n            integer(c_size_t) :: " + name + "_n"
-    a.fortran_name_post = ",\n     &      " + name + "_n"
+    a.fortran_args = [name]
+    a.fortran_types = ["character(len=GMSH_API_MAX_STR_LEN), dimension(:), allocatable, intent(out)"]
+    a.fortran_c_api = ["type(c_ptr), intent(out)", "integer(c_size_t), intent(out)"]
+    a.fortran_c_args = [api_name, api_name_n]
+    a.fortran_call = f"{api_name}={api_name}, &{api_name_n}={api_name_n}"
+    a.fortran_post = f"{name} = ovectorstring_({api_name}, &{api_name_n})"
+    a.fortran_local = [f"type(c_ptr) :: {api_name}", f"integer(c_size_t) :: {api_name_n}"]
     return a
 
 
@@ -597,9 +651,13 @@ def ovectorpair(name, value=None, python_value=None, julia_value=None):
                     "[], " + api_name_n + "[], own = true)\n    " + name +
                     " = [ (tmp_" + api_name + "[i], tmp_" + api_name +
                     "[i+1]) " + "for i in 1:2:length(tmp_" + api_name + ") ]")
-    a.fortran_type = "type(c_ptr), intent(out)"
-    a.fortran_type_post = "\n            integer(c_size_t) :: " + name + "_n"
-    a.fortran_name_post = ",\n     &      " + name + "_n"
+    a.fortran_args = [name]
+    a.fortran_types = ["integer(c_int), dimension(:,:), allocatable, intent(out)"]
+    a.fortran_c_api = ["type(c_ptr), intent(out)", "integer(c_size_t), intent(out)"]
+    a.fortran_c_args = [api_name, api_name_n]
+    a.fortran_call = f"{api_name}={api_name}, &{api_name_n}={api_name_n}"
+    a.fortran_post = f"{name} = ovectorpair_({api_name}, &{api_name_n})"
+    a.fortran_local = [f"type(c_ptr) :: {api_name}", f"integer(c_size_t) :: {api_name_n}"]
     return a
 
 
@@ -641,10 +699,13 @@ def ovectorvectorint(name, value=None, python_value=None, julia_value=None):
                     " = [ unsafe_wrap(Array, tmp_" + api_name + "[i], " +
                     "tmp_" + api_name_n + "[i], own = true) for i in 1:" +
                     api_name_nn + "[] ]")
-    a.fortran_type = "type(c_ptr), intent(out)"
-    a.fortran_type_post = ("\n            type(c_ptr), intent(out) :: " + name +
-                           "_n\n            integer(c_size_t) :: " + name +"_nn")
-    a.fortran_name_post = ",\n     &      " + name + "_n,\n     &      "  + name + "_nn"
+    a.fortran_args = [name, name + "_n"]
+    a.fortran_types = ["integer(c_int), dimension(:), allocatable, intent(out)", "integer(c_size_t), dimension(:), allocatable, intent(out)"]
+    a.fortran_c_api = ["type(c_ptr), intent(out)", "type(c_ptr), intent(out)", "integer(c_size_t), intent(out)"]
+    a.fortran_c_args = [api_name, api_name_n, api_name_nn]
+    a.fortran_call = f"{api_name}={api_name}, &{api_name_n}={api_name_n}, &{api_name_nn}={api_name_nn}"
+    a.fortran_post = f"call ovectorvectorint_({api_name}, &{api_name_n}, &{api_name_nn}, &{name}, &{name}_n)"
+    a.fortran_local = [f"type(c_ptr) :: {api_name}, {api_name_n}", f"integer(c_size_t) :: {api_name_nn}"]
     return a
 
 
@@ -686,10 +747,13 @@ def ovectorvectorsize(name, value=None, python_value=None, julia_value=None):
                     " = [ unsafe_wrap(Array, tmp_" + api_name + "[i], " +
                     "tmp_" + api_name_n + "[i], own = true) for i in 1:" +
                     api_name_nn + "[] ]")
-    a.fortran_type = "type (c_ptr), intent(out)"
-    a.fortran_type_post = ("\n            type(c_ptr), intent(out) :: " + name +
-                           "_n\n            integer(c_size_t) :: " + name +"_nn")
-    a.fortran_name_post = ",\n     &      " + name + "_n,\n     &      "  + name + "_nn"
+    a.fortran_args = [name, name + "_n"]
+    a.fortran_types = ["integer(c_size_t), dimension(:), allocatable, intent(out)", "integer(c_size_t), dimension(:), allocatable, intent(out)"]
+    a.fortran_c_api = ["type(c_ptr), intent(out)", "type(c_ptr), intent(out)", "integer(c_size_t), intent(out)"]
+    a.fortran_c_args = [api_name, api_name_n, api_name_nn]
+    a.fortran_call = f"{api_name}={api_name}, &{api_name_n}={api_name_n}, &{api_name_nn}={api_name_nn}"
+    a.fortran_post = f"call ovectorvectorsize_({api_name}, &{api_name_n}, &{api_name_nn}, &{name}, &{name}_n)"
+    a.fortran_local = [f"type(c_ptr) :: {api_name}, {api_name_n}", f"integer(c_size_t) :: {api_name_nn}"]
     return a
 
 
@@ -732,10 +796,13 @@ def ovectorvectordouble(name, value=None, python_value=None, julia_value=None):
                     " = [ unsafe_wrap(Array, tmp_" + api_name + "[i], " +
                     "tmp_" + api_name_n + "[i], own = true) for i in 1:" +
                     api_name_nn + "[] ]")
-    a.fortran_type = "type (c_ptr), intent(out)"
-    a.fortran_type_post = ("\n            type(c_ptr), intent(out) :: " + name +
-                           "_n\n            integer (c_size_t) :: " + name + "_nn")
-    a.fortran_name_post = ",\n     &      " + name + "_n,\n     &      "  + name + "_nn"
+    a.fortran_args = [name, name + "_n"]
+    a.fortran_types = ["real(c_double), dimension(:), allocatable, intent(out)", "integer(c_size_t), dimension(:), allocatable, intent(out)"]
+    a.fortran_c_api = ["type(c_ptr), intent(out)", "type(c_ptr), intent(out)", "integer(c_size_t), intent(out)"]
+    a.fortran_c_args = [api_name, api_name_n, api_name_nn]
+    a.fortran_call = f"{api_name}={api_name}, &{api_name_n}={api_name_n}, &{api_name_nn}={api_name_nn}"
+    a.fortran_post = f"call ovectorvectordouble_({api_name}, &{api_name_n}, &{api_name_nn}, &{name}, &{name}_n)"
+    a.fortran_local = [f"type(c_ptr) :: {api_name}, {api_name_n}", f"integer(c_size_t) :: {api_name_nn}"]
     return a
 
 
@@ -783,10 +850,13 @@ def ovectorvectorpair(name, value=None, python_value=None, julia_value=None):
         api_name + "[i], tmp_" + api_name_n + "[i], own = true)\n    " + "    " +
         name + "[i] = [(tmp[i], tmp[i+1]) for i in 1:2:length(tmp)]\n    " +
         "end")
-    a.fortran_type = "type (C_PTR), intent(out)"
-    a.fortran_type_post = ("\n            type(c_ptr), intent(out) :: " + name +
-                           "_n\n            integer (C_SIZE_T) ::" + name +"_nn")
-    a.fortran_name_post = ",\n     &      " + name + "_n,\n     &      "  + name + "_nn"
+    a.fortran_args = [name, name + "_n"]
+    a.fortran_types = ["integer(c_int), dimension(:,:), allocatable, intent(out)", "integer(c_size_t), dimension(:), allocatable, intent(out)"]
+    a.fortran_c_api = ["type(c_ptr), intent(out)", "type(c_ptr), intent(out)", "integer(c_size_t)"]
+    a.fortran_c_args = [api_name, api_name_n, api_name_nn]
+    a.fortran_call = f"{api_name}={api_name}, &{api_name_n}={api_name_n}, &{api_name_nn}={api_name_nn}"
+    a.fortran_post = f"call ovectorvectorpair_({api_name}, &{api_name_n}, &{api_name_nn}, &{name}, &{name}_n)"
+    a.fortran_local = [f"type(c_ptr) :: {api_name}, {api_name_n}", f"integer(c_size_t) :: {api_name_nn}"]
     return a
 
 
@@ -809,9 +879,14 @@ def iargcargv():
     a.julia_ctype = "Cint, Ptr{Ptr{Cchar}}"
     a.julia_arg = "length(argv), argv"
     a.texi = "(argc = 0)}, @code{argv = []"
-    a.fortran_name_pre = "argc,\n     &      "
-    a.fortran_type = "integer (C_INT), value :: argc\n            type (C_PTR)"
-    a.fortran_type_post = "(*)"
+    a.fortran_args = ["argv"]
+    a.fortran_types = ["character(len=*), dimension(:), intent(in), optional"]
+    a.fortran_c_api = ["integer(c_int), value, intent(in)", "type(c_ptr), dimension(*), intent(in)"]
+    a.fortran_c_args = ["argc", "argv"]
+    a.fortran_call = "argc=size_gmsh_str_array(argv), argv=argv_cptr"
+    a.fortran_pre = "call ivectorstring_(optval_str_array(def=[''], val=argv), argv_strs, argv_cptr)"
+    a.fortran_local = ["character(len=GMSH_API_MAX_STR_LEN, kind=c_char), allocatable :: argv_strs(:)",
+                       "type(c_ptr), allocatable :: argv_cptr(:)"]
     return a
 
 
@@ -849,8 +924,10 @@ def isizefun(name):
         ", Cdouble, (Cint, Cint, Cdouble, Cdouble, Cdouble, Cdouble, Ptr{Cvoid}))")
     a.julia_arg = "api_" + name + "_, C_NULL"
     a.julia_ctype = "Ptr{Cvoid}, Ptr{Cvoid}"
-    a.fortran_type = "type (C_FUNPTR)"
-    a.fortran_type_post = " ! to do "
+    a.fortran_args = [name]
+    a.fortran_types = ["type(c_funptr), value, intent(in)"]
+    a.fortran_c_api = ["type(c_funptr), value, intent(in)"]
+    a.fortran_c_args = [name]
     return a
 
 
@@ -1379,46 +1456,463 @@ julia_header = """# {0}
 """
 
 
-fortran_header = """c
-c  {0}
-c
-c  See the LICENSE.txt file in the {3} root directory for license information.
-c  Please report all issues on {1}
-c
+fortran_header = """!
+! {0}
+!
+! See the LICENSE.txt file in the {3} root directory for license information.
+! Please report all issues on {1}
 
-!DEC$ IF DEFINED ({2}F_H)
-!DEC$ ELSE
-!DEC$ DEFINE {2}F_H
+! This file defines the {3} Fortran API (v{4}.{5}.{6}).
+!
+! Do not edit this file directly: it is automatically generated by `api/gen.py'.
+!
+! By design, the {3} Fortran API is purely functional, and only uses elementary
+! Fortran types. See `tutorials/fortran' and `examples/api' for tutorials and
+! examples.
 
-c
-c  This file defines the {3} Fortran API (v{4}.{5}.{6}).
-c
-c  Do not edit this file directly: it is automatically generated by `api/gen.py'.
-c
-c  By design, the {3} Fortran API is purely functional, and only uses elementary
-c  Fortran types. See `tutorials/fortran' and `examples/api' for tutorials and
-c  examples.
-c
+module gmsh
 
-!DEC$ DEFINE {2}_API_VERSION_MAJOR = {4}
-!DEC$ DEFINE {2}_API_VERSION_MINOR = {5}
-!DEC$ DEFINE {2}_API_VERSION_PATCH = {6}
+  use, intrinsic :: iso_c_binding
 
-      module gmsh_fortran
+  implicit none
 
-        use, intrinsic :: iso_c_binding
+  private
+
+  integer, parameter, public :: {2}_API_VERSION_MAJOR = {4}
+  integer, parameter, public :: {2}_API_VERSION_MINOR = {5}
+  integer, parameter, public :: {2}_API_VERSION_PATCH = {6}
+  integer, parameter, public :: {2}_API_MAX_STR_LEN = 512
+  real(c_double), parameter, public :: M_PI = 3.14159265358979323846_c_double
+  character(len=100), parameter, public :: {2}_API_VERSION = "{4}.{5}.{6}"
+
+  public :: gmshFree
+
+  type cstr_t
+    character(len=:), allocatable :: s
+  end type cstr_t
+
+  type, private :: c_array_t
+    type(c_ptr) :: s
+  end type c_array_t
 
-        character(len = 5), parameter :: {2}_API_VERSION = "{4}.{5}.{6}"
-        real(c_double), parameter::M_PI = 3.14159265358979323846d0
+  interface optval_c_int
+    module procedure optval_c_int_1
+  end interface optval_c_int
+
+  interface optval_c_size_t
+    module procedure optval_c_size_t_1, optval_c_size_t_2
+  end interface optval_c_size_t
+
+  interface optval_c_double
+    module procedure optval_c_double_1, optval_c_double_2
+  end interface optval_c_double
 
-        interface
 """
 
 fortran_footer = """
-        end interface
-      end module gmsh_fortran
-
-!DEC$ ENDIF
+  ! ----------------------------------------------------------------------------
+  ! GMSH size function
+  ! ----------------------------------------------------------------------------
+
+  pure integer(c_int) function optval_c_int_1(def, val) result(res)
+    integer(c_int), intent(in) :: def
+    integer(c_int), optional, intent(in) :: val
+    res = int(def, kind=c_int)
+    if (present(val)) res = int(val, kind=c_int)
+  end function optval_c_int_1
+
+  pure integer(c_size_t) function optval_c_size_t_1(def, val) result(res)
+    integer, intent(in) :: def
+    integer, optional, intent(in) :: val
+    res = int(def, kind=c_size_t)
+    if (present(val)) res = int(val, kind=c_size_t)
+  end function optval_c_size_t_1
+
+  pure integer(c_size_t) function optval_c_size_t_2(def, val) result(res)
+    integer(c_size_t), intent(in) :: def
+    integer(c_size_t), optional, intent(in) :: val
+    res = int(def, kind=c_size_t)
+    if (present(val)) res = int(val, kind=c_size_t)
+  end function optval_c_size_t_2
+
+  pure real(c_double) function optval_c_double_1(def, val) result(res)
+    real(c_double), intent(in) :: def
+    real(c_double), optional, intent(in) :: val
+    res = real(def, kind=c_double)
+    if (present(val)) res = real(val, kind=c_double)
+  end function optval_c_double_1
+
+  pure real(c_double) function optval_c_double_2(def, val) result(res)
+    real, intent(in) :: def
+    real(c_double), optional, intent(in) :: val
+    res = real(def, kind=c_double)
+    if (present(val)) res = real(val, kind=c_double)
+  end function optval_c_double_2
+
+  pure integer(c_int) function optval_c_bool(def, val) result(res)
+    logical, intent(in) :: def
+    logical, optional, intent(in) :: val
+    res = merge(1_c_int, 0_c_int, def)
+    if (present(val)) res = merge(1_c_int, 0_c_int, val)
+  end function optval_c_bool
+
+  pure function optval_c_str(def, val) result(res)
+    character(len=*), intent(in) :: def
+    character(len=*), optional, intent(in) :: val
+    character(len=:), allocatable :: res
+    if (present(val)) then
+      res = val
+    else
+      res = def
+    end if
+  end function optval_c_str
+
+  pure function optval_str_array(def, val) result(res)
+    character(len=*), intent(in) :: def(:)
+    character(len=*), optional, intent(in) :: val(:)
+    character(len=:), allocatable :: res(:)
+    if (present(val)) then
+      res = val
+    else
+      res = def
+    end if
+  end function optval_str_array
+
+  ! ----------------------------------------------------------------------------
+  ! GMSH size functions, with handling of optional arguments
+  ! ----------------------------------------------------------------------------
+
+  pure integer(c_size_t) function size_gmsh_int(v) result(n)
+    integer(c_int), optional, intent(in) :: v(:)
+    n = 0
+    if (present(v)) n = size(v, kind=c_size_t)
+  end function size_gmsh_int
+
+  pure integer(c_size_t) function size_gmsh_size(v) result(n)
+    integer(c_size_t), optional, intent(in) :: v(:)
+    n = 0
+    if (present(v)) n = size(v, kind=c_size_t)
+  end function size_gmsh_size
+
+  pure integer(c_size_t) function size_gmsh_double(v) result(n)
+    real(c_double), optional, intent(in) :: v(:)
+    n = 0
+    if (present(v)) n = size(v, kind=c_size_t)
+  end function size_gmsh_double
+
+  pure integer(c_size_t) function size_gmsh_str(v) result(n)
+    character(len=*), optional, intent(in) :: v(:)
+    n = 0
+    if (present(v)) n = size(v, kind=c_size_t)
+  end function size_gmsh_str
+
+  pure integer(c_size_t) function size_gmsh_pair(v) result(n)
+    integer(c_int), optional, intent(in) :: v(:,:)
+    n = 0
+    if (present(v)) n = size(v, kind=c_size_t)
+  end function size_gmsh_pair
+
+  pure integer(c_int) function size_gmsh_str_array(v) result(n)
+    character(len=*), optional, intent(in) :: v(:)
+    n = 1   ! can't have 0-length commands
+    if (present(v)) n = size(v, kind=c_int)
+  end function size_gmsh_str_array
+
+  ! ----------------------------------------------------------------------------
+  ! GMSH C memory management tools
+  ! ----------------------------------------------------------------------------
+
+  !> Callback to C to free any reserved memory
+  subroutine gmshFree(p)
+    interface
+      subroutine C_API(ptr) bind(C, name="gmshFree")
+        use, intrinsic :: iso_c_binding
+        type(c_ptr), value :: ptr
+      end subroutine C_API
+    end interface
+    type(c_ptr) :: p
+    call C_API(p)
+  end subroutine gmshFree
+
+  ! ----------------------------------------------------------------------------
+  ! Input routines from Fortran to C
+  ! ----------------------------------------------------------------------------
+
+  function istring_(o) result(v)
+    character(len=*), intent(in) :: o
+    character(len=:, kind=c_char), allocatable :: v
+    v = trim(o)//c_null_char
+  end function istring_
+
+  function ivectorint_(o) result(v)
+    integer(c_int), intent(in) :: o(:)
+    integer(c_int), dimension(size(o)) :: v
+    v = o
+  end function ivectorint_
+
+  function ivectorsize_(o) result(v)
+    integer(c_size_t), intent(in) :: o(:)
+    integer(c_size_t), dimension(size(o)) :: v
+    v = o
+  end function ivectorsize_
+
+  function ivectordouble_(o) result(v)
+    real(c_double), intent(in) :: o(:)
+    real(c_double), dimension(size(o)) :: v
+    v = o
+  end function ivectordouble_
+
+  subroutine ivectorstring_(o, cstrs, cptrs)
+    character(len=*), intent(in) :: o(:)
+    character(len=GMSH_API_MAX_STR_LEN, kind=c_char), target, allocatable, intent(out) :: cstrs(:)
+    type(c_ptr), allocatable, intent(out) :: cptrs(:)
+    integer :: i
+    allocate(cstrs(size(o)))    ! Return to keep references from cptrs
+    allocate(cptrs(size(o)))
+    do i = 1, size(o)
+        cstrs(i) = istring_(o(i))
+        cptrs(i) = c_loc(cstrs(i))
+    end do
+  end subroutine ivectorstring_
+
+  function ivectorpair_(o) result(v)
+    integer(c_int), intent(in) :: o(:,:)
+    integer(c_int), dimension(size(o,1),2) :: v
+    v = o
+  end function ivectorpair_
+
+  subroutine ivectorvectorint_(v, dims, cptr1, cptr2, n)
+    integer(c_int), target, intent(in) :: v(:)
+    integer(c_size_t), target, intent(in) :: dims(:)
+    type(c_ptr), intent(out) :: cptr1, cptr2
+    integer(c_size_t), intent(out) :: n
+
+    n = size(dims, kind=c_size_t)
+    cptr1 = c_loc(v)
+    cptr2 = c_loc(dims)
+  end subroutine ivectorvectorint_
+
+  subroutine ivectorvectorsize_(v, dims, cptr1, cptr2, n)
+    integer(c_size_t), target, intent(in) :: v(:)
+    integer(c_size_t), target, intent(in) :: dims(:)
+    type(c_ptr), intent(out) :: cptr1, cptr2
+    integer(c_size_t), intent(out) :: n
+
+    n = size(dims, kind=c_size_t)
+    cptr1 = c_loc(v)
+    cptr2 = c_loc(dims)
+  end subroutine ivectorvectorsize_
+
+  subroutine ivectorvectordouble_(v, dims, cptr1, cptr2, n)
+    real(c_double), target, intent(in) :: v(:)
+    integer(c_size_t), target, intent(in) :: dims(:)
+    type(c_ptr), intent(out) :: cptr1, cptr2
+    integer(c_size_t), intent(out) :: n
+
+    n = size(dims, kind=c_size_t)
+    cptr1 = c_loc(v)
+    cptr2 = c_loc(dims)
+  end subroutine ivectorvectordouble_
+
+  ! subroutine ivectorvectorpair_(v, dims, cptr1, cptr2, n)
+  !   integer(c_int), target, intent(in) :: v(:,:)
+  !   integer(c_size_t), target, intent(in) :: dims(:)
+  !   type(c_ptr), intent(out) :: cptr1, cptr2
+  !   integer(c_size_t), intent(out) :: n
+  !
+  !   n = size(dims, kind=c_size_t)
+  !   cptr1 = c_loc(v)
+  !   cptr2 = c_loc(dims)
+  ! end subroutine ivectorvectorpair_
+
+
+  ! ----------------------------------------------------------------------------
+  ! Output routines from C to Fortran
+  ! ----------------------------------------------------------------------------
+
+  function ovectorint_(cptr, n) result(v)
+    type(c_ptr), intent(inout) :: cptr
+    integer(c_size_t), intent(in) :: n
+    integer(c_int), allocatable :: v(:)
+    integer(c_int), pointer :: v_(:)
+    call c_f_pointer(cptr, v_, [n])
+    allocate(v, source=v_)
+    call gmshFree(cptr)
+  end function ovectorint_
+
+  function ovectorsize_(cptr, n) result(v)
+    type(c_ptr), intent(inout) :: cptr
+    integer(c_size_t), intent(in) :: n
+    integer(c_size_t), allocatable :: v(:)
+    integer(c_size_t), pointer :: v_(:)
+    call c_f_pointer(cptr, v_, [n])
+    allocate(v, source=v_)
+    call gmshFree(cptr)
+  end function ovectorsize_
+
+  function ovectordouble_(cptr, n) result(v)
+    type(c_ptr), intent(inout) :: cptr
+    integer(c_size_t), intent(in) :: n
+    real(c_double), allocatable :: v(:)
+    real(c_double), pointer :: v_(:)
+    call c_f_pointer(cptr, v_, [n])
+    allocate(v, source=v_)
+    call gmshFree(cptr)
+  end function ovectordouble_
+
+  function ovectorstring_(cptr, n) result(v)
+    type(c_ptr), intent(inout) :: cptr
+    integer(c_size_t), intent(in) :: n
+    character(len=GMSH_API_MAX_STR_LEN), allocatable :: v(:)
+
+    integer(c_size_t) :: i, lenstr
+    type(c_array_t), pointer :: c_array(:)
+    character(kind=c_char, len=1), pointer :: fptr(:)
+
+    call c_f_pointer(cptr, c_array, [n])
+    allocate(v(n))
+    do i = 1_c_size_t, n
+        call c_f_pointer(c_array(i)%s, fptr, &
+                         [int(GMSH_API_MAX_STR_LEN, kind=c_size_t)])
+        lenstr = cstrlen(fptr)
+        v(i) = transfer(fptr(1:lenstr), v(i))
+    end do
+    call gmshFree(cptr)
+  end function ovectorstring_
+
+  function ovectorpair_(cptr, n) result(v)
+    type(c_ptr), intent(inout) :: cptr
+    integer(c_size_t), intent(in) :: n
+    integer(c_int), allocatable :: v(:,:)
+    integer(c_int), pointer :: v_(:,:)
+    call c_f_pointer(cptr, v_, [2_c_size_t, n / 2_c_size_t])
+    allocate(v, source=v_)
+    call gmshFree(cptr)
+  end function ovectorpair_
+
+  subroutine ovectorvectorint_(cptr1, cptr2, n, v, dims)
+    type(c_ptr), intent(inout) :: cptr1, cptr2
+    integer(c_size_t), intent(in) :: n
+    integer(c_int), allocatable, intent(out) :: v(:)
+    integer(c_size_t), allocatable, intent(out) :: dims(:)
+    integer(c_int), pointer :: v_(:)
+    integer(c_size_t), pointer :: dims_(:)
+    type(c_ptr), pointer :: ptrs(:)
+    integer(c_size_t) :: i, istart, iend
+    call c_f_pointer(cptr2, dims_, [n])
+    allocate(dims, source=dims_)
+    allocate(v(sum(dims_)))
+    istart = 1
+    call c_f_pointer(cptr1, ptrs, [n])
+    do i = 1_c_size_t, n
+        iend = int(dims(i))
+        call c_f_pointer(ptrs(i), v_, [iend])
+        v(istart:iend) = v_
+        istart = istart + iend
+    end do
+    do i = 1_c_size_t, n
+        call gmshFree(ptrs(i))
+    end do
+    call gmshFree(cptr1)
+    call gmshFree(cptr2)
+  end subroutine ovectorvectorint_
+
+  subroutine ovectorvectorsize_(cptr1, cptr2, n, v, dims)
+    type(c_ptr), intent(inout) :: cptr1, cptr2
+    integer(c_size_t), intent(in) :: n
+    integer(c_size_t), allocatable, intent(out) :: v(:)
+    integer(c_size_t), allocatable, intent(out) :: dims(:)
+    integer(c_size_t), pointer :: v_(:)
+    integer(c_size_t), pointer :: dims_(:)
+    type(c_ptr), pointer :: ptrs(:)
+    integer(c_size_t) :: i, istart, iend
+    call c_f_pointer(cptr2, dims_, [n])
+    allocate(dims, source=dims_)
+    allocate(v(sum(dims_)))
+    istart = 1
+    call c_f_pointer(cptr1, ptrs, [n])
+    do i = 1_c_size_t, n
+        iend = int(dims(i))
+        call c_f_pointer(ptrs(i), v_, [iend])
+        v(istart:iend) = v_
+        istart = istart + iend
+    end do
+    do i = 1_c_size_t, n
+        call gmshFree(ptrs(i))
+    end do
+    call gmshFree(cptr1)
+    call gmshFree(cptr2)
+  end subroutine ovectorvectorsize_
+
+  subroutine ovectorvectordouble_(cptr1, cptr2, n, v, dims)
+    type(c_ptr), intent(inout) :: cptr1, cptr2
+    integer(c_size_t), intent(in) :: n
+    real(c_double), allocatable, intent(out) :: v(:)
+    integer(c_size_t), allocatable, intent(out) :: dims(:)
+    real(c_double), pointer :: v_(:)
+    integer(c_size_t), pointer :: dims_(:)
+    type(c_ptr), pointer :: ptrs(:)
+    integer(c_size_t) :: i, istart, iend
+    call c_f_pointer(cptr2, dims_, [n])
+    allocate(dims, source=dims_)
+    allocate(v(sum(dims_)))
+    istart = 1
+    call c_f_pointer(cptr1, ptrs, [n])
+    do i = 1_c_size_t, n
+        iend = int(dims(i))
+        call c_f_pointer(ptrs(i), v_, [iend])
+        v(istart:iend) = v_
+        istart = istart + iend
+    end do
+    do i = 1_c_size_t, n
+        call gmshFree(ptrs(i))
+    end do
+    call gmshFree(cptr1)
+    call gmshFree(cptr2)
+  end subroutine ovectorvectordouble_
+
+  subroutine ovectorvectorpair_(cptr1, cptr2, n, v, dims)
+    type(c_ptr), intent(inout) :: cptr1, cptr2
+    integer(c_size_t), intent(in) :: n
+    integer(c_int), allocatable, intent(out) :: v(:,:)
+    integer(c_size_t), allocatable, intent(out) :: dims(:)
+    integer(c_int), pointer :: v_(:,:)
+    integer(c_size_t), pointer :: dims_(:)
+    type(c_ptr), pointer :: ptrs(:)
+    integer(c_size_t) :: i, istart, iend
+    call c_f_pointer(cptr2, dims_, [n])
+    allocate(dims, source=dims_)
+    allocate(v(2, int(sum(dims_)/2)))
+    istart = 1
+    call c_f_pointer(cptr1, ptrs, [n])
+    do i = 1_c_size_t, n
+        iend = int(dims(i)/2)
+        call c_f_pointer(ptrs(i), v_, [2_c_size_t, iend])
+        v(:,istart:iend) = v_
+        istart = istart + iend
+    end do
+    do i = 1_c_size_t, n
+        call gmshFree(ptrs(i))
+    end do
+    call gmshFree(cptr1)
+    call gmshFree(cptr2)
+  end subroutine ovectorvectorpair_
+
+  !> Calculates the length of a C string.
+  function cstrlen(carray) result(res)
+    character(kind=c_char, len=1), intent(in) :: carray(:)
+    integer :: res
+    integer :: i
+    do i = 1, size(carray)
+      if (carray(i) == c_null_char) then
+        res = i - 1
+        return
+      end if
+    end do
+    res = i
+  end function cstrlen
+
+end module gmsh
 """
 
 
@@ -1856,75 +2350,202 @@ class API:
             for module in self.modules:
                 write_module(f, module, "", "", 1)
 
-
     def write_fortran(self):
-        def write_module(module, c_namespace, cpp_namespace, indent):
-            cpp_namespace += module.name + "::"
-            if c_namespace:
-                c_namespace += module.name[0].upper() + module.name[1:]
+        types_list = []
+
+        def get_fname(name):
+            return name[0].upper() + name[1:]
+
+        def get_fc_name_t(name, c_mpath, f_mpath):
+            f_mpath += name + "_"
+            if c_mpath:
+                c_mpath += get_fname(name)
             else:
-                c_namespace = module.name
+                c_mpath = name
+            return c_mpath, f_mpath
+
+        def write_type_vars(m, c_mpath, f_mpath, indent):
+            r = ""
+            for var in m.submodules:
+                c_mpath_l, f_mpath_l = get_fc_name_t(var.name, c_mpath, f_mpath)
+                r += f"{indent}type({f_mpath_l}t) :: {var.name}\n"
+            return r
+
+        def generate_procedures(m, c_mpath, indent):
+            r = ""
+            for fun in m.fs:
+                (_, name, _, _, _) = fun
+                fname = c_mpath + get_fname(name)
+                r += f"{indent}procedure, nopass :: {name} => &\n{indent*2}{fname}\n"
+            return r
+
+        def generate_ftypes(f, m, c_mpath, f_mpath, indent):
+            c_mpath, f_mpath = get_fc_name_t(m.name, c_mpath, f_mpath)
+            r = f"{indent}type, public :: {f_mpath}t\n"
+            r += write_type_vars(m, c_mpath, f_mpath, indent * 2)
+            r += f"{indent * 2}contains\n"
+            r += generate_procedures(m, c_mpath, indent * 2)
+            r += f"{indent}end type {f_mpath}t\n"
+            # Save the types in a list
+            types_list.append(r)
+
+            for ftype in m.submodules:
+                generate_ftypes(f, ftype, c_mpath, f_mpath, indent)
+
+        def write_function(f, fun, c_mpath, f_mpath, indent):
+            def get_arg_list(args, indent):
+                arg_list = ""
+                for arg in args:
+                    # These lists contain only a single element = arg.value
+                    for t, a in zip(arg.fortran_types, arg.fortran_args):
+                        if arg.value:
+                            t += ", optional"
+                        arg_list += f"{indent}{t} :: {a}\n"
+                arg_list += f"{indent}integer(c_int), intent(out), optional :: ierr\n"
+                return arg_list
+
+            def get_c_api_arg_list(args, indent):
+                arg_list = ""
+                for arg in args:
+                    # These lists can contain multiple elements e.g. array, array_n
+                    for t, a in zip(arg.fortran_c_api, arg.fortran_c_args):
+                        # Passing by VALUE cannot be OPTIONAL
+                        if arg.value and not (", value" in t):
+                            t += f", optional"
+                        arg_list += f"{indent}{t} :: {a}\n"
+                arg_list += f"{indent}integer(c_int), intent(out), optional :: ierr_\n"
+                return arg_list
+
+            def get_dummy_arg_list(args):
+                dummy_list = ""
+                for arg in args:
+                    for a in arg.fortran_args:
+                        dummy_list += f"{a}, &"
+                dummy_list += "ierr"
+                return dummy_list
+
+            def get_c_api_call(args):
+                dummy_list = ""
+                for arg in args:
+                    if arg.fortran_call:
+                        dummy_list += f"{arg.fortran_call}, &"
+                    else:
+                        # These are single element lists
+                        for c, a in zip(arg.fortran_c_args, arg.fortran_args):
+                            dummy_list += f"{c}={a}, &"
+                dummy_list += "ierr_=ierr"
+                return dummy_list
+
+            def get_c_api_dummy_arg_list(args):
+                dummy_list = ""
+                for arg in args:
+                    for a in arg.fortran_c_args:
+                        dummy_list += f"{a}, &"
+                dummy_list += "ierr_"
+                return dummy_list
+
+            def write_c_interface(args, rtype, fname, indent):
+                proc_type = "function" if rtype else "subroutine"
+                dummy_list = get_c_api_dummy_arg_list(args)
+                r = f"{indent * 2}interface\n"
+                r += f"{indent * 2}{proc_type} C_API({dummy_list})".replace(
+                    "&", f"&\n{(len(indent * 2+proc_type+' C_API('))*' '}"
+                )
+                r += f" &\n{indent * 3}bind(C, name=\"{fname}\")\n"
+                r += f"{indent * 3}use, intrinsic :: iso_c_binding\n"
+                if rtype:
+                    r += f"{indent * 3}{rtype.fortran_c_api[0]} :: C_API\n"
 
-            indent += "  "
-            for rtype, name, args, doc, special in module.fs:
-                # *f.h
-                fname = c_namespace + name[0].upper() + name[1:]
+                r += get_c_api_arg_list(args, indent * 3)
+                r += f"{indent * 2}end {proc_type} C_API\n"
+                r += f"{indent * 2}end interface\n"
+                return r
 
-# output doc
-                self.fwrite(
-                    f,
-                    "\n!  " + "\n!  ".join(textwrap.wrap(doc, 75)) + "\n")
-                fnameapi = "!  " + ns.upper() + "_API " + (rtype.rc_type if rtype else
-                                                   "void") + " " + fname + "("
-                self.flog('f', cpp_namespace.replace('::', '/') + name)
-
-                if (len(fname) < 45) :
-
-# output fortran header
-                        fnamef = ' '*8 + ("function" if rtype else "subroutine") + ' ' + fname + "("
-                        self.fwrite(
-                            f, fnamef + "\n     &      " + (",\n     &      ").join(
-                                list((a.fortran_name_pre + a.name + a.fortran_name_post for a in args + (oint("ierr"), )))) + ")\n")
-
-                        left = "          "
-                        self.fwrite(
-                            f,
-                            "     &    bind(C, name = \"" + fname + "\")" + "\n")
-                        self.fwrite(
-                            f,
-                            left + "use, intrinsic :: iso_c_binding" + "\n")
-                        if rtype :
-                            self.fwrite(
-                                f,
-                                left + (rtype.fortran_type) + "::" + fname + "\n")
-
-                        self.fwrite(
-                            f, ("").join(
-                            list(( left + "  " + a.fortran_type + "::"
-                                   + a.name + a.fortran_type_post
-                                   + "\n" for a in args + (oint("ierr"), ) ))
-                                        )
-                                   )
-
-                        self.fwrite(
-                            f,
-                            left + "end " + ("function" if rtype else "subroutine")
-                            + " " + fname + "\n")
+            def get_local_variables(args, indent):
+                r = ""
+                for a in args:
+                    if a.fortran_local:
+                        for var in a.fortran_local:
+                            r += f"{indent}{var}\n"
+                return r
 
-            for m in module.submodules:
-                write_module(m, c_namespace, cpp_namespace, indent)
+            def get_local_setup(args, indent):
+                r = ""
+                for a in args:
+                    if a.fortran_pre:
+                        r += f"{indent}{a.fortran_pre}\n"
+                return r
+
+            def get_local_cleanup(args, indent):
+                r = ""
+                for a in args:
+                    if a.fortran_post:
+                        r += f"{indent}{a.fortran_post}\n"
+                return r
+
+            (rtype, name, args, doc, special) = fun
+            fname = c_mpath + get_fname(name)
+            # Documentation (Doxygen)
+            self.fwrite(
+                f, f"\n{indent}!> " +
+                (f"\n{indent}!! ").join(textwrap.wrap(doc, 75)) + "\n")
+
+            # Procedure declaration
+            proc_type = "function" if rtype else "subroutine"
+            fnamef = f"{proc_type} {fname}"
+            dummy_list = get_dummy_arg_list(args)
+            r = f"{indent}{fnamef}({dummy_list})\n".replace(
+                    "&", f"&\n{(len(indent+fnamef)+1)*' '}"
+                )
+            r += write_c_interface(args, rtype, fname, indent)
+            if rtype:
+                r += f"{indent * 2}{rtype.fortran_types[0]} :: {fname}\n"
+            r += get_arg_list(args, indent * 2)
+            r += f"{indent * 2}! Local variables\n"
+            # Prepare input arguments
+            r += get_local_variables(args, indent * 2)
+            r += get_local_setup(args, indent * 2).replace("&", f"&\n{indent*3}")
+            # call the C function
+            dummy_list = get_c_api_call(args)
+            if rtype:
+                r += f"{indent * 2}{fname} = C_API({dummy_list})\n".replace(
+                    "&", f"&\n{(len(indent*2)+len(fname)+3)*' '}"
+                )
+            else:
+                r += f"{indent * 2}call C_API({dummy_list})\n".replace(
+                    "&", f"&\n{(len(indent*2)+5)*' '}"
+                )
+            # Prepare output arguments
+            r += f"{indent * 2}! Post processing\n"
+            r += get_local_cleanup(args, indent * 2).replace("&", f"&\n{indent * 3}")
+            r += f"{indent}end {fnamef}\n"
+            self.fwrite(f, r)
+
+        def write_module(f, m, c_mpath, f_mpath, indent):
+            c_mpath, f_mpath = get_fc_name_t(m.name, c_mpath, f_mpath)
+            for fun in m.fs:
+                write_function(f, fun, c_mpath, f_mpath, indent)
+            for m in m.submodules:
+                write_module(f, m, c_mpath, f_mpath, indent)
 
         self.current_lineno = 1
-        with open(ns + "f.h", "w") as f:
-                    self.fwrite(
-                        f,
-                        fortran_header.format(self.copyright, self.issues,
-                                        ns.upper(), self.code,
-                                        self.version_major, self.version_minor,
-                                        self.version_patch, ns))
-                    for module in self.modules:
-                        write_module(module, "", "", "")
-                    self.fwrite(f, fortran_footer)
+        with open(ns + ".f90", "w") as f:
+            self.fwrite(
+                f,
+                fortran_header.format(self.copyright, self.issues, ns.upper(),
+                                      self.code, self.version_major,
+                                      self.version_minor, self.version_patch))
+            indent = " " * 2
+            for ftype in self.modules:
+                generate_ftypes(f, ftype, "", "", indent)
+            # Write types in reverse since they have to be defined before use
+            for ftype in reversed(types_list):
+                self.fwrite(f, ftype)
+                self.fwrite(f, "\n")
+            self.fwrite(f, f"{indent}contains\n")
+            for module in self.modules:
+                write_module(f, module, "", "", indent)
+            self.fwrite(f, fortran_footer)
 
 
     def write_texi(self):
diff --git a/api/README.txt b/api/README.txt
index 74ad730e0737ffa95436e929a938736a3bff7015..fa6e4725274acf7f2e8541c3f7d60441003fa37d 100644
--- a/api/README.txt
+++ b/api/README.txt
@@ -4,6 +4,7 @@ This directory contains the Gmsh API:
   - gmshc.h: the header defining the Gmsh C API
   - gmsh.py: the module defining the Gmsh Python API
   - gmsh.jl: the module defining the Gmsh Julia API
+  - gmsh.f90: the module defining the Gmsh Fortran API
 
 These files are all automatically generated by the Python script 'gen.py'.
 
@@ -16,8 +17,8 @@ reduced performance compared to using the native Gmsh C++ API, as it entails
 additional data copies between the C++ wrapper, the C API and the native C++
 code.
 
-See `tutorials/{c++,c,python,julia}' and `examples/api' for tutorials and
-examples on how to use the Gmsh API.
+See `tutorials/{c++,c,python,julia,fortran}' and `examples/api' for tutorials
+and examples on how to use the Gmsh API.
 
 To add a new function in the Gmsh API:
 
diff --git a/api/gen.py b/api/gen.py
index 8138f19b7d77f5fcb54d5ed1a2504b30933238f5..8b37a003a74873bf7015e0dc8a6337df18ba0565 100644
--- a/api/gen.py
+++ b/api/gen.py
@@ -13,12 +13,13 @@
 #  - gmsh.h_cwrap: the Gmsh C++ API redefined in terms of the C API
 #  - gmsh.py: the Gmsh Python API module
 #  - gmsh.jl: the Gmsh Julia API module
+#  - gmsh.f90: the Gmsh Fortran API module
 #  - api.texi: the texinfo API documentation
 #
 # By design, the Gmsh API is purely functional, and only uses elementary types
 # from the target language.
 #
-# See `tutorials/{c++,c,python,julia}' and `examples/api' for tutorials and
+# See `tutorials/{c++,c,python,julia,fortran}' and `examples/api' for tutorials and
 # examples on how to use the Gmsh API.
 
 import os
diff --git a/api/gmsh.f90 b/api/gmsh.f90
new file mode 100644
index 0000000000000000000000000000000000000000..620dddb2b8d18fd5273cb61b6a006283456a8609
--- /dev/null
+++ b/api/gmsh.f90
@@ -0,0 +1,15892 @@
+!
+! Gmsh - Copyright (C) 1997-2022 C. Geuzaine, J.-F. Remacle
+!
+! See the LICENSE.txt file in the Gmsh root directory for license information.
+! Please report all issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
+
+! This file defines the Gmsh Fortran API (v4.11.0).
+!
+! Do not edit this file directly: it is automatically generated by `api/gen.py'.
+!
+! By design, the Gmsh Fortran API is purely functional, and only uses elementary
+! Fortran types. See `tutorials/fortran' and `examples/api' for tutorials and
+! examples.
+
+module gmsh
+
+  use, intrinsic :: iso_c_binding
+
+  implicit none
+
+  private
+
+  integer, parameter, public :: GMSH_API_VERSION_MAJOR = 4
+  integer, parameter, public :: GMSH_API_VERSION_MINOR = 11
+  integer, parameter, public :: GMSH_API_VERSION_PATCH = 0
+  integer, parameter, public :: GMSH_API_MAX_STR_LEN = 512
+  real(c_double), parameter, public :: M_PI = 3.14159265358979323846_c_double
+  character(len=100), parameter, public :: GMSH_API_VERSION = "4.11.0"
+
+  public :: gmshFree
+
+  type cstr_t
+    character(len=:), allocatable :: s
+  end type cstr_t
+
+  type, private :: c_array_t
+    type(c_ptr) :: s
+  end type c_array_t
+
+  interface optval_c_int
+    module procedure optval_c_int_1
+  end interface optval_c_int
+
+  interface optval_c_size_t
+    module procedure optval_c_size_t_1, optval_c_size_t_2
+  end interface optval_c_size_t
+
+  interface optval_c_double
+    module procedure optval_c_double_1, optval_c_double_2
+  end interface optval_c_double
+
+  type, public :: gmsh_logger_t
+    contains
+    procedure, nopass :: write => &
+        gmshLoggerWrite
+    procedure, nopass :: start => &
+        gmshLoggerStart
+    procedure, nopass :: get => &
+        gmshLoggerGet
+    procedure, nopass :: stop => &
+        gmshLoggerStop
+    procedure, nopass :: getWallTime => &
+        gmshLoggerGetWallTime
+    procedure, nopass :: getCpuTime => &
+        gmshLoggerGetCpuTime
+    procedure, nopass :: getLastError => &
+        gmshLoggerGetLastError
+  end type gmsh_logger_t
+
+  type, public :: gmsh_onelab_t
+    contains
+    procedure, nopass :: set => &
+        gmshOnelabSet
+    procedure, nopass :: get => &
+        gmshOnelabGet
+    procedure, nopass :: getNames => &
+        gmshOnelabGetNames
+    procedure, nopass :: setNumber => &
+        gmshOnelabSetNumber
+    procedure, nopass :: setString => &
+        gmshOnelabSetString
+    procedure, nopass :: getNumber => &
+        gmshOnelabGetNumber
+    procedure, nopass :: getString => &
+        gmshOnelabGetString
+    procedure, nopass :: getChanged => &
+        gmshOnelabGetChanged
+    procedure, nopass :: setChanged => &
+        gmshOnelabSetChanged
+    procedure, nopass :: clear => &
+        gmshOnelabClear
+    procedure, nopass :: run => &
+        gmshOnelabRun
+  end type gmsh_onelab_t
+
+  type, public :: gmsh_parser_t
+    contains
+    procedure, nopass :: getNames => &
+        gmshParserGetNames
+    procedure, nopass :: setNumber => &
+        gmshParserSetNumber
+    procedure, nopass :: setString => &
+        gmshParserSetString
+    procedure, nopass :: getNumber => &
+        gmshParserGetNumber
+    procedure, nopass :: getString => &
+        gmshParserGetString
+    procedure, nopass :: clear => &
+        gmshParserClear
+    procedure, nopass :: parse => &
+        gmshParserParse
+  end type gmsh_parser_t
+
+  type, public :: gmsh_fltk_t
+    contains
+    procedure, nopass :: initialize => &
+        gmshFltkInitialize
+    procedure, nopass :: finalize => &
+        gmshFltkFinalize
+    procedure, nopass :: wait => &
+        gmshFltkWait
+    procedure, nopass :: update => &
+        gmshFltkUpdate
+    procedure, nopass :: awake => &
+        gmshFltkAwake
+    procedure, nopass :: lock => &
+        gmshFltkLock
+    procedure, nopass :: unlock => &
+        gmshFltkUnlock
+    procedure, nopass :: run => &
+        gmshFltkRun
+    procedure, nopass :: isAvailable => &
+        gmshFltkIsAvailable
+    procedure, nopass :: selectEntities => &
+        gmshFltkSelectEntities
+    procedure, nopass :: selectElements => &
+        gmshFltkSelectElements
+    procedure, nopass :: selectViews => &
+        gmshFltkSelectViews
+    procedure, nopass :: splitCurrentWindow => &
+        gmshFltkSplitCurrentWindow
+    procedure, nopass :: setCurrentWindow => &
+        gmshFltkSetCurrentWindow
+    procedure, nopass :: setStatusMessage => &
+        gmshFltkSetStatusMessage
+    procedure, nopass :: showContextWindow => &
+        gmshFltkShowContextWindow
+    procedure, nopass :: openTreeItem => &
+        gmshFltkOpenTreeItem
+    procedure, nopass :: closeTreeItem => &
+        gmshFltkCloseTreeItem
+  end type gmsh_fltk_t
+
+  type, public :: gmsh_graphics_t
+    contains
+    procedure, nopass :: draw => &
+        gmshGraphicsDraw
+  end type gmsh_graphics_t
+
+  type, public :: gmsh_plugin_t
+    contains
+    procedure, nopass :: setNumber => &
+        gmshPluginSetNumber
+    procedure, nopass :: setString => &
+        gmshPluginSetString
+    procedure, nopass :: run => &
+        gmshPluginRun
+  end type gmsh_plugin_t
+
+  type, public :: gmsh_view_option_t
+    contains
+    procedure, nopass :: setNumber => &
+        gmshViewOptionSetNumber
+    procedure, nopass :: getNumber => &
+        gmshViewOptionGetNumber
+    procedure, nopass :: setString => &
+        gmshViewOptionSetString
+    procedure, nopass :: getString => &
+        gmshViewOptionGetString
+    procedure, nopass :: setColor => &
+        gmshViewOptionSetColor
+    procedure, nopass :: getColor => &
+        gmshViewOptionGetColor
+    procedure, nopass :: copy => &
+        gmshViewOptionCopy
+  end type gmsh_view_option_t
+
+  type, public :: gmsh_view_t
+    type(gmsh_view_option_t) :: option
+    contains
+    procedure, nopass :: add => &
+        gmshViewAdd
+    procedure, nopass :: remove => &
+        gmshViewRemove
+    procedure, nopass :: getIndex => &
+        gmshViewGetIndex
+    procedure, nopass :: getTags => &
+        gmshViewGetTags
+    procedure, nopass :: addModelData => &
+        gmshViewAddModelData
+    procedure, nopass :: addHomogeneousModelData => &
+        gmshViewAddHomogeneousModelData
+    procedure, nopass :: getModelData => &
+        gmshViewGetModelData
+    procedure, nopass :: getHomogeneousModelData => &
+        gmshViewGetHomogeneousModelData
+    procedure, nopass :: addListData => &
+        gmshViewAddListData
+    procedure, nopass :: getListData => &
+        gmshViewGetListData
+    procedure, nopass :: addListDataString => &
+        gmshViewAddListDataString
+    procedure, nopass :: getListDataStrings => &
+        gmshViewGetListDataStrings
+    procedure, nopass :: setInterpolationMatrices => &
+        gmshViewSetInterpolationMatrices
+    procedure, nopass :: addAlias => &
+        gmshViewAddAlias
+    procedure, nopass :: combine => &
+        gmshViewCombine
+    procedure, nopass :: probe => &
+        gmshViewProbe
+    procedure, nopass :: write => &
+        gmshViewWrite
+    procedure, nopass :: setVisibilityPerWindow => &
+        gmshViewSetVisibilityPerWindow
+  end type gmsh_view_t
+
+  type, public :: gmsh_model_occ_mesh_t
+    contains
+    procedure, nopass :: setSize => &
+        gmshModelOccMeshSetSize
+  end type gmsh_model_occ_mesh_t
+
+  type, public :: gmsh_model_occ_t
+    type(gmsh_model_occ_mesh_t) :: mesh
+    contains
+    procedure, nopass :: addPoint => &
+        gmshModelOccAddPoint
+    procedure, nopass :: addLine => &
+        gmshModelOccAddLine
+    procedure, nopass :: addCircleArc => &
+        gmshModelOccAddCircleArc
+    procedure, nopass :: addCircle => &
+        gmshModelOccAddCircle
+    procedure, nopass :: addEllipseArc => &
+        gmshModelOccAddEllipseArc
+    procedure, nopass :: addEllipse => &
+        gmshModelOccAddEllipse
+    procedure, nopass :: addSpline => &
+        gmshModelOccAddSpline
+    procedure, nopass :: addBSpline => &
+        gmshModelOccAddBSpline
+    procedure, nopass :: addBezier => &
+        gmshModelOccAddBezier
+    procedure, nopass :: addWire => &
+        gmshModelOccAddWire
+    procedure, nopass :: addCurveLoop => &
+        gmshModelOccAddCurveLoop
+    procedure, nopass :: addRectangle => &
+        gmshModelOccAddRectangle
+    procedure, nopass :: addDisk => &
+        gmshModelOccAddDisk
+    procedure, nopass :: addPlaneSurface => &
+        gmshModelOccAddPlaneSurface
+    procedure, nopass :: addSurfaceFilling => &
+        gmshModelOccAddSurfaceFilling
+    procedure, nopass :: addBSplineFilling => &
+        gmshModelOccAddBSplineFilling
+    procedure, nopass :: addBezierFilling => &
+        gmshModelOccAddBezierFilling
+    procedure, nopass :: addBSplineSurface => &
+        gmshModelOccAddBSplineSurface
+    procedure, nopass :: addBezierSurface => &
+        gmshModelOccAddBezierSurface
+    procedure, nopass :: addTrimmedSurface => &
+        gmshModelOccAddTrimmedSurface
+    procedure, nopass :: addSurfaceLoop => &
+        gmshModelOccAddSurfaceLoop
+    procedure, nopass :: addVolume => &
+        gmshModelOccAddVolume
+    procedure, nopass :: addSphere => &
+        gmshModelOccAddSphere
+    procedure, nopass :: addBox => &
+        gmshModelOccAddBox
+    procedure, nopass :: addCylinder => &
+        gmshModelOccAddCylinder
+    procedure, nopass :: addCone => &
+        gmshModelOccAddCone
+    procedure, nopass :: addWedge => &
+        gmshModelOccAddWedge
+    procedure, nopass :: addTorus => &
+        gmshModelOccAddTorus
+    procedure, nopass :: addThruSections => &
+        gmshModelOccAddThruSections
+    procedure, nopass :: addThickSolid => &
+        gmshModelOccAddThickSolid
+    procedure, nopass :: extrude => &
+        gmshModelOccExtrude
+    procedure, nopass :: revolve => &
+        gmshModelOccRevolve
+    procedure, nopass :: addPipe => &
+        gmshModelOccAddPipe
+    procedure, nopass :: fillet => &
+        gmshModelOccFillet
+    procedure, nopass :: chamfer => &
+        gmshModelOccChamfer
+    procedure, nopass :: fuse => &
+        gmshModelOccFuse
+    procedure, nopass :: intersect => &
+        gmshModelOccIntersect
+    procedure, nopass :: cut => &
+        gmshModelOccCut
+    procedure, nopass :: fragment => &
+        gmshModelOccFragment
+    procedure, nopass :: translate => &
+        gmshModelOccTranslate
+    procedure, nopass :: rotate => &
+        gmshModelOccRotate
+    procedure, nopass :: dilate => &
+        gmshModelOccDilate
+    procedure, nopass :: mirror => &
+        gmshModelOccMirror
+    procedure, nopass :: symmetrize => &
+        gmshModelOccSymmetrize
+    procedure, nopass :: affineTransform => &
+        gmshModelOccAffineTransform
+    procedure, nopass :: copy => &
+        gmshModelOccCopy
+    procedure, nopass :: remove => &
+        gmshModelOccRemove
+    procedure, nopass :: removeAllDuplicates => &
+        gmshModelOccRemoveAllDuplicates
+    procedure, nopass :: healShapes => &
+        gmshModelOccHealShapes
+    procedure, nopass :: convertToNURBS => &
+        gmshModelOccConvertToNURBS
+    procedure, nopass :: importShapes => &
+        gmshModelOccImportShapes
+    procedure, nopass :: importShapesNativePointer => &
+        gmshModelOccImportShapesNativePointer
+    procedure, nopass :: getEntities => &
+        gmshModelOccGetEntities
+    procedure, nopass :: getEntitiesInBoundingBox => &
+        gmshModelOccGetEntitiesInBoundingBox
+    procedure, nopass :: getBoundingBox => &
+        gmshModelOccGetBoundingBox
+    procedure, nopass :: getCurveLoops => &
+        gmshModelOccGetCurveLoops
+    procedure, nopass :: getSurfaceLoops => &
+        gmshModelOccGetSurfaceLoops
+    procedure, nopass :: getMass => &
+        gmshModelOccGetMass
+    procedure, nopass :: getCenterOfMass => &
+        gmshModelOccGetCenterOfMass
+    procedure, nopass :: getMatrixOfInertia => &
+        gmshModelOccGetMatrixOfInertia
+    procedure, nopass :: getMaxTag => &
+        gmshModelOccGetMaxTag
+    procedure, nopass :: setMaxTag => &
+        gmshModelOccSetMaxTag
+    procedure, nopass :: synchronize => &
+        gmshModelOccSynchronize
+  end type gmsh_model_occ_t
+
+  type, public :: gmsh_model_geo_mesh_t
+    contains
+    procedure, nopass :: setSize => &
+        gmshModelGeoMeshSetSize
+    procedure, nopass :: setTransfiniteCurve => &
+        gmshModelGeoMeshSetTransfiniteCurve
+    procedure, nopass :: setTransfiniteSurface => &
+        gmshModelGeoMeshSetTransfiniteSurface
+    procedure, nopass :: setTransfiniteVolume => &
+        gmshModelGeoMeshSetTransfiniteVolume
+    procedure, nopass :: setRecombine => &
+        gmshModelGeoMeshSetRecombine
+    procedure, nopass :: setSmoothing => &
+        gmshModelGeoMeshSetSmoothing
+    procedure, nopass :: setReverse => &
+        gmshModelGeoMeshSetReverse
+    procedure, nopass :: setAlgorithm => &
+        gmshModelGeoMeshSetAlgorithm
+    procedure, nopass :: setSizeFromBoundary => &
+        gmshModelGeoMeshSetSizeFromBoundary
+  end type gmsh_model_geo_mesh_t
+
+  type, public :: gmsh_model_geo_t
+    type(gmsh_model_geo_mesh_t) :: mesh
+    contains
+    procedure, nopass :: addPoint => &
+        gmshModelGeoAddPoint
+    procedure, nopass :: addLine => &
+        gmshModelGeoAddLine
+    procedure, nopass :: addCircleArc => &
+        gmshModelGeoAddCircleArc
+    procedure, nopass :: addEllipseArc => &
+        gmshModelGeoAddEllipseArc
+    procedure, nopass :: addSpline => &
+        gmshModelGeoAddSpline
+    procedure, nopass :: addBSpline => &
+        gmshModelGeoAddBSpline
+    procedure, nopass :: addBezier => &
+        gmshModelGeoAddBezier
+    procedure, nopass :: addPolyline => &
+        gmshModelGeoAddPolyline
+    procedure, nopass :: addCompoundSpline => &
+        gmshModelGeoAddCompoundSpline
+    procedure, nopass :: addCompoundBSpline => &
+        gmshModelGeoAddCompoundBSpline
+    procedure, nopass :: addCurveLoop => &
+        gmshModelGeoAddCurveLoop
+    procedure, nopass :: addCurveLoops => &
+        gmshModelGeoAddCurveLoops
+    procedure, nopass :: addPlaneSurface => &
+        gmshModelGeoAddPlaneSurface
+    procedure, nopass :: addSurfaceFilling => &
+        gmshModelGeoAddSurfaceFilling
+    procedure, nopass :: addSurfaceLoop => &
+        gmshModelGeoAddSurfaceLoop
+    procedure, nopass :: addVolume => &
+        gmshModelGeoAddVolume
+    procedure, nopass :: addGeometry => &
+        gmshModelGeoAddGeometry
+    procedure, nopass :: addPointOnGeometry => &
+        gmshModelGeoAddPointOnGeometry
+    procedure, nopass :: extrude => &
+        gmshModelGeoExtrude
+    procedure, nopass :: revolve => &
+        gmshModelGeoRevolve
+    procedure, nopass :: twist => &
+        gmshModelGeoTwist
+    procedure, nopass :: extrudeBoundaryLayer => &
+        gmshModelGeoExtrudeBoundaryLayer
+    procedure, nopass :: translate => &
+        gmshModelGeoTranslate
+    procedure, nopass :: rotate => &
+        gmshModelGeoRotate
+    procedure, nopass :: dilate => &
+        gmshModelGeoDilate
+    procedure, nopass :: mirror => &
+        gmshModelGeoMirror
+    procedure, nopass :: symmetrize => &
+        gmshModelGeoSymmetrize
+    procedure, nopass :: copy => &
+        gmshModelGeoCopy
+    procedure, nopass :: remove => &
+        gmshModelGeoRemove
+    procedure, nopass :: removeAllDuplicates => &
+        gmshModelGeoRemoveAllDuplicates
+    procedure, nopass :: splitCurve => &
+        gmshModelGeoSplitCurve
+    procedure, nopass :: getMaxTag => &
+        gmshModelGeoGetMaxTag
+    procedure, nopass :: setMaxTag => &
+        gmshModelGeoSetMaxTag
+    procedure, nopass :: addPhysicalGroup => &
+        gmshModelGeoAddPhysicalGroup
+    procedure, nopass :: removePhysicalGroups => &
+        gmshModelGeoRemovePhysicalGroups
+    procedure, nopass :: synchronize => &
+        gmshModelGeoSynchronize
+  end type gmsh_model_geo_t
+
+  type, public :: gmsh_model_mesh_field_t
+    contains
+    procedure, nopass :: add => &
+        gmshModelMeshFieldAdd
+    procedure, nopass :: remove => &
+        gmshModelMeshFieldRemove
+    procedure, nopass :: list => &
+        gmshModelMeshFieldList
+    procedure, nopass :: getType => &
+        gmshModelMeshFieldGetType
+    procedure, nopass :: setNumber => &
+        gmshModelMeshFieldSetNumber
+    procedure, nopass :: getNumber => &
+        gmshModelMeshFieldGetNumber
+    procedure, nopass :: setString => &
+        gmshModelMeshFieldSetString
+    procedure, nopass :: getString => &
+        gmshModelMeshFieldGetString
+    procedure, nopass :: setNumbers => &
+        gmshModelMeshFieldSetNumbers
+    procedure, nopass :: getNumbers => &
+        gmshModelMeshFieldGetNumbers
+    procedure, nopass :: setAsBackgroundMesh => &
+        gmshModelMeshFieldSetAsBackgroundMesh
+    procedure, nopass :: setAsBoundaryLayer => &
+        gmshModelMeshFieldSetAsBoundaryLayer
+  end type gmsh_model_mesh_field_t
+
+  type, public :: gmsh_model_mesh_t
+    type(gmsh_model_mesh_field_t) :: field
+    contains
+    procedure, nopass :: generate => &
+        gmshModelMeshGenerate
+    procedure, nopass :: partition => &
+        gmshModelMeshPartition
+    procedure, nopass :: unpartition => &
+        gmshModelMeshUnpartition
+    procedure, nopass :: optimize => &
+        gmshModelMeshOptimize
+    procedure, nopass :: recombine => &
+        gmshModelMeshRecombine
+    procedure, nopass :: refine => &
+        gmshModelMeshRefine
+    procedure, nopass :: setOrder => &
+        gmshModelMeshSetOrder
+    procedure, nopass :: getLastEntityError => &
+        gmshModelMeshGetLastEntityError
+    procedure, nopass :: getLastNodeError => &
+        gmshModelMeshGetLastNodeError
+    procedure, nopass :: clear => &
+        gmshModelMeshClear
+    procedure, nopass :: reverse => &
+        gmshModelMeshReverse
+    procedure, nopass :: affineTransform => &
+        gmshModelMeshAffineTransform
+    procedure, nopass :: getNodes => &
+        gmshModelMeshGetNodes
+    procedure, nopass :: getNodesByElementType => &
+        gmshModelMeshGetNodesByElementType
+    procedure, nopass :: getNode => &
+        gmshModelMeshGetNode
+    procedure, nopass :: setNode => &
+        gmshModelMeshSetNode
+    procedure, nopass :: rebuildNodeCache => &
+        gmshModelMeshRebuildNodeCache
+    procedure, nopass :: rebuildElementCache => &
+        gmshModelMeshRebuildElementCache
+    procedure, nopass :: getNodesForPhysicalGroup => &
+        gmshModelMeshGetNodesForPhysicalGroup
+    procedure, nopass :: getMaxNodeTag => &
+        gmshModelMeshGetMaxNodeTag
+    procedure, nopass :: addNodes => &
+        gmshModelMeshAddNodes
+    procedure, nopass :: reclassifyNodes => &
+        gmshModelMeshReclassifyNodes
+    procedure, nopass :: relocateNodes => &
+        gmshModelMeshRelocateNodes
+    procedure, nopass :: getElements => &
+        gmshModelMeshGetElements
+    procedure, nopass :: getElement => &
+        gmshModelMeshGetElement
+    procedure, nopass :: getElementByCoordinates => &
+        gmshModelMeshGetElementByCoordinates
+    procedure, nopass :: getElementsByCoordinates => &
+        gmshModelMeshGetElementsByCoordinates
+    procedure, nopass :: getLocalCoordinatesInElement => &
+        gmshModelMeshGetLocalCoordinatesInElement
+    procedure, nopass :: getElementTypes => &
+        gmshModelMeshGetElementTypes
+    procedure, nopass :: getElementType => &
+        gmshModelMeshGetElementType
+    procedure, nopass :: getElementProperties => &
+        gmshModelMeshGetElementProperties
+    procedure, nopass :: getElementsByType => &
+        gmshModelMeshGetElementsByType
+    procedure, nopass :: getMaxElementTag => &
+        gmshModelMeshGetMaxElementTag
+    procedure, nopass :: preallocateElementsByType => &
+        gmshModelMeshPreallocateElementsByType
+    procedure, nopass :: getElementQualities => &
+        gmshModelMeshGetElementQualities
+    procedure, nopass :: addElements => &
+        gmshModelMeshAddElements
+    procedure, nopass :: addElementsByType => &
+        gmshModelMeshAddElementsByType
+    procedure, nopass :: getIntegrationPoints => &
+        gmshModelMeshGetIntegrationPoints
+    procedure, nopass :: getJacobians => &
+        gmshModelMeshGetJacobians
+    procedure, nopass :: preallocateJacobians => &
+        gmshModelMeshPreallocateJacobians
+    procedure, nopass :: getJacobian => &
+        gmshModelMeshGetJacobian
+    procedure, nopass :: getBasisFunctions => &
+        gmshModelMeshGetBasisFunctions
+    procedure, nopass :: getBasisFunctionsOrientation => &
+        gmshModelMeshGetBasisFunctionsOrientation
+    procedure, nopass :: getBasisFunctionsOrientationForElement => &
+        gmshModelMeshGetBasisFunctionsOrientationForElement
+    procedure, nopass :: getNumberOfOrientations => &
+        gmshModelMeshGetNumberOfOrientations
+    procedure, nopass :: preallocateBasisFunctionsOrientation => &
+        gmshModelMeshPreallocateBasisFunctionsOrientation
+    procedure, nopass :: getEdges => &
+        gmshModelMeshGetEdges
+    procedure, nopass :: getFaces => &
+        gmshModelMeshGetFaces
+    procedure, nopass :: createEdges => &
+        gmshModelMeshCreateEdges
+    procedure, nopass :: createFaces => &
+        gmshModelMeshCreateFaces
+    procedure, nopass :: getAllEdges => &
+        gmshModelMeshGetAllEdges
+    procedure, nopass :: getAllFaces => &
+        gmshModelMeshGetAllFaces
+    procedure, nopass :: addEdges => &
+        gmshModelMeshAddEdges
+    procedure, nopass :: addFaces => &
+        gmshModelMeshAddFaces
+    procedure, nopass :: getKeys => &
+        gmshModelMeshGetKeys
+    procedure, nopass :: getKeysForElement => &
+        gmshModelMeshGetKeysForElement
+    procedure, nopass :: getNumberOfKeys => &
+        gmshModelMeshGetNumberOfKeys
+    procedure, nopass :: getKeysInformation => &
+        gmshModelMeshGetKeysInformation
+    procedure, nopass :: getBarycenters => &
+        gmshModelMeshGetBarycenters
+    procedure, nopass :: preallocateBarycenters => &
+        gmshModelMeshPreallocateBarycenters
+    procedure, nopass :: getElementEdgeNodes => &
+        gmshModelMeshGetElementEdgeNodes
+    procedure, nopass :: getElementFaceNodes => &
+        gmshModelMeshGetElementFaceNodes
+    procedure, nopass :: getGhostElements => &
+        gmshModelMeshGetGhostElements
+    procedure, nopass :: setSize => &
+        gmshModelMeshSetSize
+    procedure, nopass :: getSizes => &
+        gmshModelMeshGetSizes
+    procedure, nopass :: setSizeAtParametricPoints => &
+        gmshModelMeshSetSizeAtParametricPoints
+    procedure, nopass :: setSizeCallback => &
+        gmshModelMeshSetSizeCallback
+    procedure, nopass :: removeSizeCallback => &
+        gmshModelMeshRemoveSizeCallback
+    procedure, nopass :: setTransfiniteCurve => &
+        gmshModelMeshSetTransfiniteCurve
+    procedure, nopass :: setTransfiniteSurface => &
+        gmshModelMeshSetTransfiniteSurface
+    procedure, nopass :: setTransfiniteVolume => &
+        gmshModelMeshSetTransfiniteVolume
+    procedure, nopass :: setTransfiniteAutomatic => &
+        gmshModelMeshSetTransfiniteAutomatic
+    procedure, nopass :: setRecombine => &
+        gmshModelMeshSetRecombine
+    procedure, nopass :: setSmoothing => &
+        gmshModelMeshSetSmoothing
+    procedure, nopass :: setReverse => &
+        gmshModelMeshSetReverse
+    procedure, nopass :: setAlgorithm => &
+        gmshModelMeshSetAlgorithm
+    procedure, nopass :: setSizeFromBoundary => &
+        gmshModelMeshSetSizeFromBoundary
+    procedure, nopass :: setCompound => &
+        gmshModelMeshSetCompound
+    procedure, nopass :: setOutwardOrientation => &
+        gmshModelMeshSetOutwardOrientation
+    procedure, nopass :: removeConstraints => &
+        gmshModelMeshRemoveConstraints
+    procedure, nopass :: embed => &
+        gmshModelMeshEmbed
+    procedure, nopass :: removeEmbedded => &
+        gmshModelMeshRemoveEmbedded
+    procedure, nopass :: getEmbedded => &
+        gmshModelMeshGetEmbedded
+    procedure, nopass :: reorderElements => &
+        gmshModelMeshReorderElements
+    procedure, nopass :: renumberNodes => &
+        gmshModelMeshRenumberNodes
+    procedure, nopass :: renumberElements => &
+        gmshModelMeshRenumberElements
+    procedure, nopass :: setPeriodic => &
+        gmshModelMeshSetPeriodic
+    procedure, nopass :: getPeriodic => &
+        gmshModelMeshGetPeriodic
+    procedure, nopass :: getPeriodicNodes => &
+        gmshModelMeshGetPeriodicNodes
+    procedure, nopass :: getPeriodicKeys => &
+        gmshModelMeshGetPeriodicKeys
+    procedure, nopass :: importStl => &
+        gmshModelMeshImportStl
+    procedure, nopass :: getDuplicateNodes => &
+        gmshModelMeshGetDuplicateNodes
+    procedure, nopass :: removeDuplicateNodes => &
+        gmshModelMeshRemoveDuplicateNodes
+    procedure, nopass :: removeDuplicateElements => &
+        gmshModelMeshRemoveDuplicateElements
+    procedure, nopass :: splitQuadrangles => &
+        gmshModelMeshSplitQuadrangles
+    procedure, nopass :: setVisibility => &
+        gmshModelMeshSetVisibility
+    procedure, nopass :: classifySurfaces => &
+        gmshModelMeshClassifySurfaces
+    procedure, nopass :: createGeometry => &
+        gmshModelMeshCreateGeometry
+    procedure, nopass :: createTopology => &
+        gmshModelMeshCreateTopology
+    procedure, nopass :: addHomologyRequest => &
+        gmshModelMeshAddHomologyRequest
+    procedure, nopass :: clearHomologyRequests => &
+        gmshModelMeshClearHomologyRequests
+    procedure, nopass :: computeHomology => &
+        gmshModelMeshComputeHomology
+    procedure, nopass :: computeCrossField => &
+        gmshModelMeshComputeCrossField
+    procedure, nopass :: triangulate => &
+        gmshModelMeshTriangulate
+    procedure, nopass :: tetrahedralize => &
+        gmshModelMeshTetrahedralize
+  end type gmsh_model_mesh_t
+
+  type, public :: gmsh_model_t
+    type(gmsh_model_mesh_t) :: mesh
+    type(gmsh_model_geo_t) :: geo
+    type(gmsh_model_occ_t) :: occ
+    contains
+    procedure, nopass :: add => &
+        gmshModelAdd
+    procedure, nopass :: remove => &
+        gmshModelRemove
+    procedure, nopass :: list => &
+        gmshModelList
+    procedure, nopass :: getCurrent => &
+        gmshModelGetCurrent
+    procedure, nopass :: setCurrent => &
+        gmshModelSetCurrent
+    procedure, nopass :: getFileName => &
+        gmshModelGetFileName
+    procedure, nopass :: setFileName => &
+        gmshModelSetFileName
+    procedure, nopass :: getEntities => &
+        gmshModelGetEntities
+    procedure, nopass :: setEntityName => &
+        gmshModelSetEntityName
+    procedure, nopass :: getEntityName => &
+        gmshModelGetEntityName
+    procedure, nopass :: getPhysicalGroups => &
+        gmshModelGetPhysicalGroups
+    procedure, nopass :: getEntitiesForPhysicalGroup => &
+        gmshModelGetEntitiesForPhysicalGroup
+    procedure, nopass :: getPhysicalGroupsForEntity => &
+        gmshModelGetPhysicalGroupsForEntity
+    procedure, nopass :: addPhysicalGroup => &
+        gmshModelAddPhysicalGroup
+    procedure, nopass :: removePhysicalGroups => &
+        gmshModelRemovePhysicalGroups
+    procedure, nopass :: setPhysicalName => &
+        gmshModelSetPhysicalName
+    procedure, nopass :: removePhysicalName => &
+        gmshModelRemovePhysicalName
+    procedure, nopass :: getPhysicalName => &
+        gmshModelGetPhysicalName
+    procedure, nopass :: setTag => &
+        gmshModelSetTag
+    procedure, nopass :: getBoundary => &
+        gmshModelGetBoundary
+    procedure, nopass :: getAdjacencies => &
+        gmshModelGetAdjacencies
+    procedure, nopass :: getEntitiesInBoundingBox => &
+        gmshModelGetEntitiesInBoundingBox
+    procedure, nopass :: getBoundingBox => &
+        gmshModelGetBoundingBox
+    procedure, nopass :: getDimension => &
+        gmshModelGetDimension
+    procedure, nopass :: addDiscreteEntity => &
+        gmshModelAddDiscreteEntity
+    procedure, nopass :: removeEntities => &
+        gmshModelRemoveEntities
+    procedure, nopass :: removeEntityName => &
+        gmshModelRemoveEntityName
+    procedure, nopass :: getType => &
+        gmshModelGetType
+    procedure, nopass :: getParent => &
+        gmshModelGetParent
+    procedure, nopass :: getNumberOfPartitions => &
+        gmshModelGetNumberOfPartitions
+    procedure, nopass :: getPartitions => &
+        gmshModelGetPartitions
+    procedure, nopass :: getValue => &
+        gmshModelGetValue
+    procedure, nopass :: getDerivative => &
+        gmshModelGetDerivative
+    procedure, nopass :: getSecondDerivative => &
+        gmshModelGetSecondDerivative
+    procedure, nopass :: getCurvature => &
+        gmshModelGetCurvature
+    procedure, nopass :: getPrincipalCurvatures => &
+        gmshModelGetPrincipalCurvatures
+    procedure, nopass :: getNormal => &
+        gmshModelGetNormal
+    procedure, nopass :: getParametrization => &
+        gmshModelGetParametrization
+    procedure, nopass :: getParametrizationBounds => &
+        gmshModelGetParametrizationBounds
+    procedure, nopass :: isInside => &
+        gmshModelIsInside
+    procedure, nopass :: getClosestPoint => &
+        gmshModelGetClosestPoint
+    procedure, nopass :: reparametrizeOnSurface => &
+        gmshModelReparametrizeOnSurface
+    procedure, nopass :: setVisibility => &
+        gmshModelSetVisibility
+    procedure, nopass :: getVisibility => &
+        gmshModelGetVisibility
+    procedure, nopass :: setVisibilityPerWindow => &
+        gmshModelSetVisibilityPerWindow
+    procedure, nopass :: setColor => &
+        gmshModelSetColor
+    procedure, nopass :: getColor => &
+        gmshModelGetColor
+    procedure, nopass :: setCoordinates => &
+        gmshModelSetCoordinates
+    procedure, nopass :: getAttributeNames => &
+        gmshModelGetAttributeNames
+    procedure, nopass :: getAttribute => &
+        gmshModelGetAttribute
+    procedure, nopass :: setAttribute => &
+        gmshModelSetAttribute
+    procedure, nopass :: removeAttribute => &
+        gmshModelRemoveAttribute
+  end type gmsh_model_t
+
+  type, public :: gmsh_option_t
+    contains
+    procedure, nopass :: setNumber => &
+        gmshOptionSetNumber
+    procedure, nopass :: getNumber => &
+        gmshOptionGetNumber
+    procedure, nopass :: setString => &
+        gmshOptionSetString
+    procedure, nopass :: getString => &
+        gmshOptionGetString
+    procedure, nopass :: setColor => &
+        gmshOptionSetColor
+    procedure, nopass :: getColor => &
+        gmshOptionGetColor
+  end type gmsh_option_t
+
+  type, public :: gmsh_t
+    type(gmsh_option_t) :: option
+    type(gmsh_model_t) :: model
+    type(gmsh_view_t) :: view
+    type(gmsh_plugin_t) :: plugin
+    type(gmsh_graphics_t) :: graphics
+    type(gmsh_fltk_t) :: fltk
+    type(gmsh_parser_t) :: parser
+    type(gmsh_onelab_t) :: onelab
+    type(gmsh_logger_t) :: logger
+    contains
+    procedure, nopass :: initialize => &
+        gmshInitialize
+    procedure, nopass :: isInitialized => &
+        gmshIsInitialized
+    procedure, nopass :: finalize => &
+        gmshFinalize
+    procedure, nopass :: open => &
+        gmshOpen
+    procedure, nopass :: merge => &
+        gmshMerge
+    procedure, nopass :: write => &
+        gmshWrite
+    procedure, nopass :: clear => &
+        gmshClear
+  end type gmsh_t
+
+  contains
+
+  !> Initialize the Gmsh API. This must be called before any call to the other
+  !! functions in the API. If `argc' and `argv' (or just `argv' in Python or
+  !! Julia) are provided, they will be handled in the same way as the command
+  !! line arguments in the Gmsh app. If `readConfigFiles' is set, read system
+  !! Gmsh configuration files (gmshrc and gmsh-options). If `run' is set, run in
+  !! the same way as the Gmsh app, either interactively or in batch mode
+  !! depending on the command line arguments. If `run' is not set, initializing
+  !! the API sets the options "General.AbortOnError" to 2 and "General.Terminal"
+  !! to 1.
+  subroutine gmshInitialize(argv, &
+                            readConfigFiles, &
+                            run, &
+                            ierr)
+    interface
+    subroutine C_API(argc, &
+                     argv, &
+                     readConfigFiles, &
+                     run, &
+                     ierr_) &
+      bind(C, name="gmshInitialize")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: argc
+      type(c_ptr), dimension(*), intent(in) :: argv
+      integer(c_int), value, intent(in) :: readConfigFiles
+      integer(c_int), value, intent(in) :: run
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), dimension(:), intent(in), optional :: argv
+    logical, intent(in), optional :: readConfigFiles
+    logical, intent(in), optional :: run
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    character(len=GMSH_API_MAX_STR_LEN, kind=c_char), allocatable :: argv_strs(:)
+    type(c_ptr), allocatable :: argv_cptr(:)
+    call ivectorstring_(optval_str_array(def=[''], val=argv), argv_strs, argv_cptr)
+    call C_API(argc=size_gmsh_str_array(argv), argv=argv_cptr, &
+         readConfigFiles=optval_c_bool(.true., readConfigFiles), &
+         run=optval_c_bool(.false., run), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshInitialize
+
+  !> Return 1 if the Gmsh API is initialized, and 0 if not.
+  function gmshIsInitialized(ierr)
+    interface
+    function C_API(ierr_) &
+      bind(C, name="gmshIsInitialized")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshIsInitialized
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshIsInitialized = C_API(ierr_=ierr)
+    ! Post processing
+  end function gmshIsInitialized
+
+  !> Finalize the Gmsh API. This must be called when you are done using the Gmsh
+  !! API.
+  subroutine gmshFinalize(ierr)
+    interface
+    subroutine C_API(ierr_) &
+      bind(C, name="gmshFinalize")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(ierr_=ierr)
+    ! Post processing
+  end subroutine gmshFinalize
+
+  !> Open a file. Equivalent to the `File->Open' menu in the Gmsh app. Handling
+  !! of the file depends on its extension and/or its contents: opening a file
+  !! with model data will create a new model.
+  subroutine gmshOpen(fileName, &
+                      ierr)
+    interface
+    subroutine C_API(fileName, &
+                     ierr_) &
+      bind(C, name="gmshOpen")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: fileName
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: fileName
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(fileName=istring_(fileName), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshOpen
+
+  !> Merge a file. Equivalent to the `File->Merge' menu in the Gmsh app.
+  !! Handling of the file depends on its extension and/or its contents. Merging
+  !! a file with model data will add the data to the current model.
+  subroutine gmshMerge(fileName, &
+                       ierr)
+    interface
+    subroutine C_API(fileName, &
+                     ierr_) &
+      bind(C, name="gmshMerge")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: fileName
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: fileName
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(fileName=istring_(fileName), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshMerge
+
+  !> Write a file. The export format is determined by the file extension.
+  subroutine gmshWrite(fileName, &
+                       ierr)
+    interface
+    subroutine C_API(fileName, &
+                     ierr_) &
+      bind(C, name="gmshWrite")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: fileName
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: fileName
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(fileName=istring_(fileName), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshWrite
+
+  !> Clear all loaded models and post-processing data, and add a new empty
+  !! model.
+  subroutine gmshClear(ierr)
+    interface
+    subroutine C_API(ierr_) &
+      bind(C, name="gmshClear")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(ierr_=ierr)
+    ! Post processing
+  end subroutine gmshClear
+
+  !> Set 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.
+  subroutine gmshOptionSetNumber(name, &
+                                 value, &
+                                 ierr)
+    interface
+    subroutine C_API(name, &
+                     value, &
+                     ierr_) &
+      bind(C, name="gmshOptionSetNumber")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      real(c_double), value, intent(in) :: value
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: name
+    real(c_double), intent(in) :: value
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(name=istring_(name), &
+         value=real(value, c_double), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshOptionSetNumber
+
+  !> Get the `value' of a numerical option. `name' is of the form
+  !! "Category.Option" or "Category[num].Option". Available categories and
+  !! options are listed in the Gmsh reference manual.
+  subroutine gmshOptionGetNumber(name, &
+                                 value, &
+                                 ierr)
+    interface
+    subroutine C_API(name, &
+                     value, &
+                     ierr_) &
+      bind(C, name="gmshOptionGetNumber")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      real(c_double) :: value
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: name
+    real(c_double) :: value
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(name=istring_(name), &
+         value=value, &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshOptionGetNumber
+
+  !> Set a string 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.
+  subroutine gmshOptionSetString(name, &
+                                 value, &
+                                 ierr)
+    interface
+    subroutine C_API(name, &
+                     value, &
+                     ierr_) &
+      bind(C, name="gmshOptionSetString")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      character(len=1, kind=c_char), dimension(*), intent(in) :: value
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: name
+    character(len=*), intent(in) :: value
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(name=istring_(name), &
+         value=istring_(value), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshOptionSetString
+
+  !> Get the `value' of a string option. `name' is of the form "Category.Option"
+  !! or "Category[num].Option". Available categories and options are listed in
+  !! the Gmsh reference manual.
+  subroutine gmshOptionGetString(name, &
+                                 value, &
+                                 ierr)
+    interface
+    subroutine C_API(name, &
+                     api_value_, &
+                     ierr_) &
+      bind(C, name="gmshOptionGetString")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      character(kind=c_char), dimension(*) :: api_value_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: name
+    character(len=:), allocatable, intent(out) :: value
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(name=istring_(name), &
+         api_value_=value, &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshOptionGetString
+
+  !> Set a color option to the RGBA value (`r', `g', `b', `a'), where where `r',
+  !! `g', `b' and `a' should be integers between 0 and 255. `name' is of the
+  !! form "Category.Color.Option" or "Category[num].Color.Option". Available
+  !! categories and options are listed in the Gmsh reference manual. For
+  !! conciseness "Color." can be ommitted in `name'.
+  subroutine gmshOptionSetColor(name, &
+                                r, &
+                                g, &
+                                b, &
+                                a, &
+                                ierr)
+    interface
+    subroutine C_API(name, &
+                     r, &
+                     g, &
+                     b, &
+                     a, &
+                     ierr_) &
+      bind(C, name="gmshOptionSetColor")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      integer(c_int), value, intent(in) :: r
+      integer(c_int), value, intent(in) :: g
+      integer(c_int), value, intent(in) :: b
+      integer(c_int), value, intent(in) :: a
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: name
+    integer, intent(in) :: r
+    integer, intent(in) :: g
+    integer, intent(in) :: b
+    integer, intent(in), optional :: a
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(name=istring_(name), &
+         r=int(r, c_int), &
+         g=int(g, c_int), &
+         b=int(b, c_int), &
+         a=optval_c_int(255, a), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshOptionSetColor
+
+  !> Get the `r', `g', `b', `a' value of a color option. `name' is of the form
+  !! "Category.Color.Option" or "Category[num].Color.Option". Available
+  !! categories and options are listed in the Gmsh reference manual. For
+  !! conciseness "Color." can be ommitted in `name'.
+  subroutine gmshOptionGetColor(name, &
+                                r, &
+                                g, &
+                                b, &
+                                a, &
+                                ierr)
+    interface
+    subroutine C_API(name, &
+                     r, &
+                     g, &
+                     b, &
+                     a, &
+                     ierr_) &
+      bind(C, name="gmshOptionGetColor")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      integer(c_int) :: r
+      integer(c_int) :: g
+      integer(c_int) :: b
+      integer(c_int) :: a
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: name
+    integer(c_int) :: r
+    integer(c_int) :: g
+    integer(c_int) :: b
+    integer(c_int) :: a
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(name=istring_(name), &
+         r=r, &
+         g=g, &
+         b=b, &
+         a=a, &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshOptionGetColor
+
+  !> Add a new model, with name `name', and set it as the current model.
+  subroutine gmshModelAdd(name, &
+                          ierr)
+    interface
+    subroutine C_API(name, &
+                     ierr_) &
+      bind(C, name="gmshModelAdd")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: name
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(name=istring_(name), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelAdd
+
+  !> Remove the current model.
+  subroutine gmshModelRemove(ierr)
+    interface
+    subroutine C_API(ierr_) &
+      bind(C, name="gmshModelRemove")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelRemove
+
+  !> List the names of all models.
+  subroutine gmshModelList(names, &
+                           ierr)
+    interface
+    subroutine C_API(api_names_, &
+                     api_names_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelList")
+      use, intrinsic :: iso_c_binding
+      type(c_ptr), intent(out) :: api_names_
+      integer(c_size_t), intent(out) :: api_names_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=GMSH_API_MAX_STR_LEN), dimension(:), allocatable, intent(out) :: names
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_names_
+    integer(c_size_t) :: api_names_n_
+    call C_API(api_names_=api_names_, &
+         api_names_n_=api_names_n_, &
+         ierr_=ierr)
+    ! Post processing
+    names = ovectorstring_(api_names_, &
+      api_names_n_)
+  end subroutine gmshModelList
+
+  !> Get the name of the current model.
+  subroutine gmshModelGetCurrent(name, &
+                                 ierr)
+    interface
+    subroutine C_API(api_name_, &
+                     ierr_) &
+      bind(C, name="gmshModelGetCurrent")
+      use, intrinsic :: iso_c_binding
+      character(kind=c_char), dimension(*) :: api_name_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=:), allocatable, intent(out) :: name
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_name_=name, &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelGetCurrent
+
+  !> Set the current model to the model with name `name'. If several models have
+  !! the same name, select the one that was added first.
+  subroutine gmshModelSetCurrent(name, &
+                                 ierr)
+    interface
+    subroutine C_API(name, &
+                     ierr_) &
+      bind(C, name="gmshModelSetCurrent")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: name
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(name=istring_(name), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelSetCurrent
+
+  !> Get the file name (if any) associated with the current model. A file name
+  !! is associated when a model is read from a file on disk.
+  subroutine gmshModelGetFileName(fileName, &
+                                  ierr)
+    interface
+    subroutine C_API(api_fileName_, &
+                     ierr_) &
+      bind(C, name="gmshModelGetFileName")
+      use, intrinsic :: iso_c_binding
+      character(kind=c_char), dimension(*) :: api_fileName_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=:), allocatable, intent(out) :: fileName
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_fileName_=fileName, &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelGetFileName
+
+  !> Set the file name associated with the current model.
+  subroutine gmshModelSetFileName(fileName, &
+                                  ierr)
+    interface
+    subroutine C_API(fileName, &
+                     ierr_) &
+      bind(C, name="gmshModelSetFileName")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: fileName
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: fileName
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(fileName=istring_(fileName), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelSetFileName
+
+  !> Get all the entities in the current model. If `dim' is >= 0, return 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.
+  subroutine gmshModelGetEntities(dimTags, &
+                                  dim, &
+                                  ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     dim, &
+                     ierr_) &
+      bind(C, name="gmshModelGetEntities")
+      use, intrinsic :: iso_c_binding
+      type(c_ptr), intent(out) :: api_dimTags_
+      integer(c_size_t), intent(out) :: api_dimTags_n_
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: dimTags
+    integer, intent(in), optional :: dim
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_dimTags_
+    integer(c_size_t) :: api_dimTags_n_
+    call C_API(api_dimTags_=api_dimTags_, &
+         api_dimTags_n_=api_dimTags_n_, &
+         dim=optval_c_int(-1, dim), &
+         ierr_=ierr)
+    ! Post processing
+    dimTags = ovectorpair_(api_dimTags_, &
+      api_dimTags_n_)
+  end subroutine gmshModelGetEntities
+
+  !> Set the name of the entity of dimension `dim' and tag `tag'.
+  subroutine gmshModelSetEntityName(dim, &
+                                    tag, &
+                                    name, &
+                                    ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     name, &
+                     ierr_) &
+      bind(C, name="gmshModelSetEntityName")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    character(len=*), intent(in) :: name
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         name=istring_(name), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelSetEntityName
+
+  !> Get the name of the entity of dimension `dim' and tag `tag'.
+  subroutine gmshModelGetEntityName(dim, &
+                                    tag, &
+                                    name, &
+                                    ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     api_name_, &
+                     ierr_) &
+      bind(C, name="gmshModelGetEntityName")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      character(kind=c_char), dimension(*) :: api_name_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    character(len=:), allocatable, intent(out) :: name
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         api_name_=name, &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelGetEntityName
+
+  !> Get all the physical groups in the current model. If `dim' is >= 0, return
+  !! 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.
+  subroutine gmshModelGetPhysicalGroups(dimTags, &
+                                        dim, &
+                                        ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     dim, &
+                     ierr_) &
+      bind(C, name="gmshModelGetPhysicalGroups")
+      use, intrinsic :: iso_c_binding
+      type(c_ptr), intent(out) :: api_dimTags_
+      integer(c_size_t), intent(out) :: api_dimTags_n_
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: dimTags
+    integer, intent(in), optional :: dim
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_dimTags_
+    integer(c_size_t) :: api_dimTags_n_
+    call C_API(api_dimTags_=api_dimTags_, &
+         api_dimTags_n_=api_dimTags_n_, &
+         dim=optval_c_int(-1, dim), &
+         ierr_=ierr)
+    ! Post processing
+    dimTags = ovectorpair_(api_dimTags_, &
+      api_dimTags_n_)
+  end subroutine gmshModelGetPhysicalGroups
+
+  !> Get the tags of the model entities making up the physical group of
+  !! dimension `dim' and tag `tag'.
+  subroutine gmshModelGetEntitiesForPhysicalGroup(dim, &
+                                                  tag, &
+                                                  tags, &
+                                                  ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     api_tags_, &
+                     api_tags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelGetEntitiesForPhysicalGroup")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      type(c_ptr), intent(out) :: api_tags_
+      integer(c_size_t), intent(out) :: api_tags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    integer(c_int), dimension(:), allocatable, intent(out) :: tags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_tags_
+    integer(c_size_t) :: api_tags_n_
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         api_tags_=api_tags_, &
+         api_tags_n_=api_tags_n_, &
+         ierr_=ierr)
+    ! Post processing
+    tags = ovectorint_(api_tags_, &
+      api_tags_n_)
+  end subroutine gmshModelGetEntitiesForPhysicalGroup
+
+  !> Get the tags of the physical groups (if any) to which the model entity of
+  !! dimension `dim' and tag `tag' belongs.
+  subroutine gmshModelGetPhysicalGroupsForEntity(dim, &
+                                                 tag, &
+                                                 physicalTags, &
+                                                 ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     api_physicalTags_, &
+                     api_physicalTags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelGetPhysicalGroupsForEntity")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      type(c_ptr), intent(out) :: api_physicalTags_
+      integer(c_size_t), intent(out) :: api_physicalTags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    integer(c_int), dimension(:), allocatable, intent(out) :: physicalTags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_physicalTags_
+    integer(c_size_t) :: api_physicalTags_n_
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         api_physicalTags_=api_physicalTags_, &
+         api_physicalTags_n_=api_physicalTags_n_, &
+         ierr_=ierr)
+    ! Post processing
+    physicalTags = ovectorint_(api_physicalTags_, &
+      api_physicalTags_n_)
+  end subroutine gmshModelGetPhysicalGroupsForEntity
+
+  !> Add a physical group of dimension `dim', grouping the model entities with
+  !! tags `tags'. Return the tag of the physical group, equal to `tag' if `tag'
+  !! is positive, or a new tag if `tag' < 0. Set the name of the physical group
+  !! if `name' is not empty.
+  function gmshModelAddPhysicalGroup(dim, &
+                                     tags, &
+                                     tag, &
+                                     name, &
+                                     ierr)
+    interface
+    function C_API(dim, &
+                   api_tags_, &
+                   api_tags_n_, &
+                   tag, &
+                   name, &
+                   ierr_) &
+      bind(C, name="gmshModelAddPhysicalGroup")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), dimension(*) :: api_tags_
+      integer(c_size_t), value, intent(in) :: api_tags_n_
+      integer(c_int), value, intent(in) :: tag
+      character(len=1, kind=c_char), dimension(*), intent(in), optional :: name
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelAddPhysicalGroup
+    integer, intent(in) :: dim
+    integer(c_int), dimension(:), intent(in) :: tags
+    integer, intent(in), optional :: tag
+    character(len=*), intent(in), optional :: name
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelAddPhysicalGroup = C_API(dim=int(dim, c_int), &
+                                api_tags_=tags, &
+                                api_tags_n_=size_gmsh_int(tags), &
+                                tag=optval_c_int(-1, tag), &
+                                name=istring_(optval_c_str("", name)), &
+                                ierr_=ierr)
+    ! Post processing
+  end function gmshModelAddPhysicalGroup
+
+  !> Remove the physical groups `dimTags' from the current model. If `dimTags'
+  !! is empty, remove all groups.
+  subroutine gmshModelRemovePhysicalGroups(dimTags, &
+                                           ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelRemovePhysicalGroups")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*), optional :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in), optional :: dimTags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelRemovePhysicalGroups
+
+  !> Set the name of the physical group of dimension `dim' and tag `tag'.
+  subroutine gmshModelSetPhysicalName(dim, &
+                                      tag, &
+                                      name, &
+                                      ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     name, &
+                     ierr_) &
+      bind(C, name="gmshModelSetPhysicalName")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    character(len=*), intent(in) :: name
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         name=istring_(name), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelSetPhysicalName
+
+  !> Remove the physical name `name' from the current model.
+  subroutine gmshModelRemovePhysicalName(name, &
+                                         ierr)
+    interface
+    subroutine C_API(name, &
+                     ierr_) &
+      bind(C, name="gmshModelRemovePhysicalName")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: name
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(name=istring_(name), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelRemovePhysicalName
+
+  !> Get the name of the physical group of dimension `dim' and tag `tag'.
+  subroutine gmshModelGetPhysicalName(dim, &
+                                      tag, &
+                                      name, &
+                                      ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     api_name_, &
+                     ierr_) &
+      bind(C, name="gmshModelGetPhysicalName")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      character(kind=c_char), dimension(*) :: api_name_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    character(len=:), allocatable, intent(out) :: name
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         api_name_=name, &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelGetPhysicalName
+
+  !> Set the tag of the entity of dimension `dim' and tag `tag' to the new value
+  !! `newTag'.
+  subroutine gmshModelSetTag(dim, &
+                             tag, &
+                             newTag, &
+                             ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     newTag, &
+                     ierr_) &
+      bind(C, name="gmshModelSetTag")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: newTag
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    integer, intent(in) :: newTag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         newTag=int(newTag, c_int), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelSetTag
+
+  !> Get the boundary of the model entities `dimTags'. Return 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). Return tags multiplied by the sign of the boundary
+  !! entity if `oriented' is true. Apply the boundary operator recursively down
+  !! to dimension 0 (i.e. to points) if `recursive' is true.
+  subroutine gmshModelGetBoundary(dimTags, &
+                                  outDimTags, &
+                                  combined, &
+                                  oriented, &
+                                  recursive, &
+                                  ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     api_outDimTags_, &
+                     api_outDimTags_n_, &
+                     combined, &
+                     oriented, &
+                     recursive, &
+                     ierr_) &
+      bind(C, name="gmshModelGetBoundary")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      type(c_ptr), intent(out) :: api_outDimTags_
+      integer(c_size_t), intent(out) :: api_outDimTags_n_
+      integer(c_int), value, intent(in) :: combined
+      integer(c_int), value, intent(in) :: oriented
+      integer(c_int), value, intent(in) :: recursive
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: outDimTags
+    logical, intent(in), optional :: combined
+    logical, intent(in), optional :: oriented
+    logical, intent(in), optional :: recursive
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_outDimTags_
+    integer(c_size_t) :: api_outDimTags_n_
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         api_outDimTags_=api_outDimTags_, &
+         api_outDimTags_n_=api_outDimTags_n_, &
+         combined=optval_c_bool(.true., combined), &
+         oriented=optval_c_bool(.true., oriented), &
+         recursive=optval_c_bool(.false., recursive), &
+         ierr_=ierr)
+    ! Post processing
+    outDimTags = ovectorpair_(api_outDimTags_, &
+      api_outDimTags_n_)
+  end subroutine gmshModelGetBoundary
+
+  !> Get the upward and downward adjacencies of the model entity of dimension
+  !! `dim' and tag `tag'. The `upward' vector returns the adjacent entities of
+  !! dimension `dim' + 1; the `downward' vector returns the adjacent entities of
+  !! dimension `dim' - 1.
+  subroutine gmshModelGetAdjacencies(dim, &
+                                     tag, &
+                                     upward, &
+                                     downward, &
+                                     ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     api_upward_, &
+                     api_upward_n_, &
+                     api_downward_, &
+                     api_downward_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelGetAdjacencies")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      type(c_ptr), intent(out) :: api_upward_
+      integer(c_size_t), intent(out) :: api_upward_n_
+      type(c_ptr), intent(out) :: api_downward_
+      integer(c_size_t), intent(out) :: api_downward_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    integer(c_int), dimension(:), allocatable, intent(out) :: upward
+    integer(c_int), dimension(:), allocatable, intent(out) :: downward
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_upward_
+    integer(c_size_t) :: api_upward_n_
+    type(c_ptr) :: api_downward_
+    integer(c_size_t) :: api_downward_n_
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         api_upward_=api_upward_, &
+         api_upward_n_=api_upward_n_, &
+         api_downward_=api_downward_, &
+         api_downward_n_=api_downward_n_, &
+         ierr_=ierr)
+    ! Post processing
+    upward = ovectorint_(api_upward_, &
+      api_upward_n_)
+    downward = ovectorint_(api_downward_, &
+      api_downward_n_)
+  end subroutine gmshModelGetAdjacencies
+
+  !> Get the model entities in the bounding box defined by the two points
+  !! (`xmin', `ymin', `zmin') and (`xmax', `ymax', `zmax'). If `dim' is >= 0,
+  !! return only the entities of the specified dimension (e.g. points if `dim'
+  !! == 0).
+  subroutine gmshModelGetEntitiesInBoundingBox(xmin, &
+                                               ymin, &
+                                               zmin, &
+                                               xmax, &
+                                               ymax, &
+                                               zmax, &
+                                               tags, &
+                                               dim, &
+                                               ierr)
+    interface
+    subroutine C_API(xmin, &
+                     ymin, &
+                     zmin, &
+                     xmax, &
+                     ymax, &
+                     zmax, &
+                     api_tags_, &
+                     api_tags_n_, &
+                     dim, &
+                     ierr_) &
+      bind(C, name="gmshModelGetEntitiesInBoundingBox")
+      use, intrinsic :: iso_c_binding
+      real(c_double), value, intent(in) :: xmin
+      real(c_double), value, intent(in) :: ymin
+      real(c_double), value, intent(in) :: zmin
+      real(c_double), value, intent(in) :: xmax
+      real(c_double), value, intent(in) :: ymax
+      real(c_double), value, intent(in) :: zmax
+      type(c_ptr), intent(out) :: api_tags_
+      integer(c_size_t), intent(out) :: api_tags_n_
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    real(c_double), intent(in) :: xmin
+    real(c_double), intent(in) :: ymin
+    real(c_double), intent(in) :: zmin
+    real(c_double), intent(in) :: xmax
+    real(c_double), intent(in) :: ymax
+    real(c_double), intent(in) :: zmax
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: tags
+    integer, intent(in), optional :: dim
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_tags_
+    integer(c_size_t) :: api_tags_n_
+    call C_API(xmin=real(xmin, c_double), &
+         ymin=real(ymin, c_double), &
+         zmin=real(zmin, c_double), &
+         xmax=real(xmax, c_double), &
+         ymax=real(ymax, c_double), &
+         zmax=real(zmax, c_double), &
+         api_tags_=api_tags_, &
+         api_tags_n_=api_tags_n_, &
+         dim=optval_c_int(-1, dim), &
+         ierr_=ierr)
+    ! Post processing
+    tags = ovectorpair_(api_tags_, &
+      api_tags_n_)
+  end subroutine gmshModelGetEntitiesInBoundingBox
+
+  !> Get the bounding box (`xmin', `ymin', `zmin'), (`xmax', `ymax', `zmax') of
+  !! the model entity of dimension `dim' and tag `tag'. If `dim' and `tag' are
+  !! negative, get the bounding box of the whole model.
+  subroutine gmshModelGetBoundingBox(dim, &
+                                     tag, &
+                                     xmin, &
+                                     ymin, &
+                                     zmin, &
+                                     xmax, &
+                                     ymax, &
+                                     zmax, &
+                                     ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     xmin, &
+                     ymin, &
+                     zmin, &
+                     xmax, &
+                     ymax, &
+                     zmax, &
+                     ierr_) &
+      bind(C, name="gmshModelGetBoundingBox")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      real(c_double) :: xmin
+      real(c_double) :: ymin
+      real(c_double) :: zmin
+      real(c_double) :: xmax
+      real(c_double) :: ymax
+      real(c_double) :: zmax
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    real(c_double) :: xmin
+    real(c_double) :: ymin
+    real(c_double) :: zmin
+    real(c_double) :: xmax
+    real(c_double) :: ymax
+    real(c_double) :: zmax
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         xmin=xmin, &
+         ymin=ymin, &
+         zmin=zmin, &
+         xmax=xmax, &
+         ymax=ymax, &
+         zmax=zmax, &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelGetBoundingBox
+
+  !> Return the geometrical dimension of the current model.
+  function gmshModelGetDimension(ierr)
+    interface
+    function C_API(ierr_) &
+      bind(C, name="gmshModelGetDimension")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelGetDimension
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelGetDimension = C_API(ierr_=ierr)
+    ! Post processing
+  end function gmshModelGetDimension
+
+  !> Add a discrete model entity (defined by a mesh) of dimension `dim' in the
+  !! current model. Return 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. Specifying
+  !! `boundary' allows Gmsh to construct the topology of the overall model.
+  function gmshModelAddDiscreteEntity(dim, &
+                                      tag, &
+                                      boundary, &
+                                      ierr)
+    interface
+    function C_API(dim, &
+                   tag, &
+                   api_boundary_, &
+                   api_boundary_n_, &
+                   ierr_) &
+      bind(C, name="gmshModelAddDiscreteEntity")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), dimension(*), optional :: api_boundary_
+      integer(c_size_t), value, intent(in) :: api_boundary_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelAddDiscreteEntity
+    integer, intent(in) :: dim
+    integer, intent(in), optional :: tag
+    integer(c_int), dimension(:), intent(in), optional :: boundary
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelAddDiscreteEntity = C_API(dim=int(dim, c_int), &
+                                 tag=optval_c_int(-1, tag), &
+                                 api_boundary_=boundary, &
+                                 api_boundary_n_=size_gmsh_int(boundary), &
+                                 ierr_=ierr)
+    ! Post processing
+  end function gmshModelAddDiscreteEntity
+
+  !> Remove the entities `dimTags' of the current model, provided that they are
+  !! not on the boundary of (or embedded in) higher-dimensional entities. If
+  !! `recursive' is true, remove all the entities on their boundaries, down to
+  !! dimension 0.
+  subroutine gmshModelRemoveEntities(dimTags, &
+                                     recursive, &
+                                     ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     recursive, &
+                     ierr_) &
+      bind(C, name="gmshModelRemoveEntities")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      integer(c_int), value, intent(in) :: recursive
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    logical, intent(in), optional :: recursive
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         recursive=optval_c_bool(.false., recursive), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelRemoveEntities
+
+  !> Remove the entity name `name' from the current model.
+  subroutine gmshModelRemoveEntityName(name, &
+                                       ierr)
+    interface
+    subroutine C_API(name, &
+                     ierr_) &
+      bind(C, name="gmshModelRemoveEntityName")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: name
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(name=istring_(name), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelRemoveEntityName
+
+  !> Get the type of the entity of dimension `dim' and tag `tag'.
+  subroutine gmshModelGetType(dim, &
+                              tag, &
+                              entityType, &
+                              ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     api_entityType_, &
+                     ierr_) &
+      bind(C, name="gmshModelGetType")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      character(kind=c_char), dimension(*) :: api_entityType_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    character(len=:), allocatable, intent(out) :: entityType
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         api_entityType_=entityType, &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelGetType
+
+  !> In a partitioned model, get the parent of the entity of dimension `dim' and
+  !! tag `tag', i.e. from which the entity is a part of, if any. `parentDim' and
+  !! `parentTag' are set to -1 if the entity has no parent.
+  subroutine gmshModelGetParent(dim, &
+                                tag, &
+                                parentDim, &
+                                parentTag, &
+                                ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     parentDim, &
+                     parentTag, &
+                     ierr_) &
+      bind(C, name="gmshModelGetParent")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int) :: parentDim
+      integer(c_int) :: parentTag
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    integer(c_int) :: parentDim
+    integer(c_int) :: parentTag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         parentDim=parentDim, &
+         parentTag=parentTag, &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelGetParent
+
+  !> Return the number of partitions in the model.
+  function gmshModelGetNumberOfPartitions(ierr)
+    interface
+    function C_API(ierr_) &
+      bind(C, name="gmshModelGetNumberOfPartitions")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelGetNumberOfPartitions
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelGetNumberOfPartitions = C_API(ierr_=ierr)
+    ! Post processing
+  end function gmshModelGetNumberOfPartitions
+
+  !> In a partitioned model, return the tags of the partition(s) to which the
+  !! entity belongs.
+  subroutine gmshModelGetPartitions(dim, &
+                                    tag, &
+                                    partitions, &
+                                    ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     api_partitions_, &
+                     api_partitions_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelGetPartitions")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      type(c_ptr), intent(out) :: api_partitions_
+      integer(c_size_t), intent(out) :: api_partitions_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    integer(c_int), dimension(:), allocatable, intent(out) :: partitions
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_partitions_
+    integer(c_size_t) :: api_partitions_n_
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         api_partitions_=api_partitions_, &
+         api_partitions_n_=api_partitions_n_, &
+         ierr_=ierr)
+    ! Post processing
+    partitions = ovectorint_(api_partitions_, &
+      api_partitions_n_)
+  end subroutine gmshModelGetPartitions
+
+  !> Evaluate the parametrization of the entity of dimension `dim' and tag `tag'
+  !! at the parametric coordinates `parametricCoord'. Only valid for `dim' equal
+  !! to 0 (with empty `parametricCoord'), 1 (with `parametricCoord' containing
+  !! parametric coordinates on the curve) or 2 (with `parametricCoord'
+  !! containing pairs of u, v parametric coordinates on the surface,
+  !! concatenated: [p1u, p1v, p2u, ...]). Return triplets of x, y, z coordinates
+  !! in `coord', concatenated: [p1x, p1y, p1z, p2x, ...].
+  subroutine gmshModelGetValue(dim, &
+                               tag, &
+                               parametricCoord, &
+                               coord, &
+                               ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     api_parametricCoord_, &
+                     api_parametricCoord_n_, &
+                     api_coord_, &
+                     api_coord_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelGetValue")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      real(c_double), dimension(*) :: api_parametricCoord_
+      integer(c_size_t), value, intent(in) :: api_parametricCoord_n_
+      type(c_ptr), intent(out) :: api_coord_
+      integer(c_size_t) :: api_coord_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    real(c_double), dimension(:), intent(in) :: parametricCoord
+    real(c_double), dimension(:), allocatable, intent(out) :: coord
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_coord_
+    integer(c_size_t) :: api_coord_n_
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         api_parametricCoord_=parametricCoord, &
+         api_parametricCoord_n_=size_gmsh_double(parametricCoord), &
+         api_coord_=api_coord_, &
+         api_coord_n_=api_coord_n_, &
+         ierr_=ierr)
+    ! Post processing
+    coord = ovectordouble_(api_coord_, &
+      api_coord_n_)
+  end subroutine gmshModelGetValue
+
+  !> Evaluate the derivative of the parametrization of the entity of dimension
+  !! `dim' and tag `tag' at the parametric coordinates `parametricCoord'. Only
+  !! valid for `dim' equal to 1 (with `parametricCoord' containing parametric
+  !! coordinates on the curve) or 2 (with `parametricCoord' containing pairs of
+  !! u, v parametric coordinates on the surface, concatenated: [p1u, p1v, p2u,
+  !! ...]). For `dim' equal to 1 return the x, y, z components of the derivative
+  !! with respect to u [d1ux, d1uy, d1uz, d2ux, ...]; for `dim' equal to 2
+  !! return the x, y, z components of the derivative with respect to u and v:
+  !! [d1ux, d1uy, d1uz, d1vx, d1vy, d1vz, d2ux, ...].
+  subroutine gmshModelGetDerivative(dim, &
+                                    tag, &
+                                    parametricCoord, &
+                                    derivatives, &
+                                    ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     api_parametricCoord_, &
+                     api_parametricCoord_n_, &
+                     api_derivatives_, &
+                     api_derivatives_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelGetDerivative")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      real(c_double), dimension(*) :: api_parametricCoord_
+      integer(c_size_t), value, intent(in) :: api_parametricCoord_n_
+      type(c_ptr), intent(out) :: api_derivatives_
+      integer(c_size_t) :: api_derivatives_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    real(c_double), dimension(:), intent(in) :: parametricCoord
+    real(c_double), dimension(:), allocatable, intent(out) :: derivatives
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_derivatives_
+    integer(c_size_t) :: api_derivatives_n_
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         api_parametricCoord_=parametricCoord, &
+         api_parametricCoord_n_=size_gmsh_double(parametricCoord), &
+         api_derivatives_=api_derivatives_, &
+         api_derivatives_n_=api_derivatives_n_, &
+         ierr_=ierr)
+    ! Post processing
+    derivatives = ovectordouble_(api_derivatives_, &
+      api_derivatives_n_)
+  end subroutine gmshModelGetDerivative
+
+  !> Evaluate the second derivative of the parametrization of the entity of
+  !! dimension `dim' and tag `tag' at the parametric coordinates
+  !! `parametricCoord'. Only valid for `dim' equal to 1 (with `parametricCoord'
+  !! containing parametric coordinates on the curve) or 2 (with
+  !! `parametricCoord' containing pairs of u, v parametric coordinates on the
+  !! surface, concatenated: [p1u, p1v, p2u, ...]). For `dim' equal to 1 return
+  !! the x, y, z components of the second derivative with respect to u [d1uux,
+  !! d1uuy, d1uuz, d2uux, ...]; for `dim' equal to 2 return the x, y, z
+  !! components of the second derivative with respect to u and v, and the mixed
+  !! derivative with respect to u and v: [d1uux, d1uuy, d1uuz, d1vvx, d1vvy,
+  !! d1vvz, d1uvx, d1uvy, d1uvz, d2uux, ...].
+  subroutine gmshModelGetSecondDerivative(dim, &
+                                          tag, &
+                                          parametricCoord, &
+                                          derivatives, &
+                                          ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     api_parametricCoord_, &
+                     api_parametricCoord_n_, &
+                     api_derivatives_, &
+                     api_derivatives_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelGetSecondDerivative")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      real(c_double), dimension(*) :: api_parametricCoord_
+      integer(c_size_t), value, intent(in) :: api_parametricCoord_n_
+      type(c_ptr), intent(out) :: api_derivatives_
+      integer(c_size_t) :: api_derivatives_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    real(c_double), dimension(:), intent(in) :: parametricCoord
+    real(c_double), dimension(:), allocatable, intent(out) :: derivatives
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_derivatives_
+    integer(c_size_t) :: api_derivatives_n_
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         api_parametricCoord_=parametricCoord, &
+         api_parametricCoord_n_=size_gmsh_double(parametricCoord), &
+         api_derivatives_=api_derivatives_, &
+         api_derivatives_n_=api_derivatives_n_, &
+         ierr_=ierr)
+    ! Post processing
+    derivatives = ovectordouble_(api_derivatives_, &
+      api_derivatives_n_)
+  end subroutine gmshModelGetSecondDerivative
+
+  !> Evaluate the (maximum) curvature of the entity of dimension `dim' and tag
+  !! `tag' at the parametric coordinates `parametricCoord'. Only valid for `dim'
+  !! equal to 1 (with `parametricCoord' containing parametric coordinates on the
+  !! curve) or 2 (with `parametricCoord' containing pairs of u, v parametric
+  !! coordinates on the surface, concatenated: [p1u, p1v, p2u, ...]).
+  subroutine gmshModelGetCurvature(dim, &
+                                   tag, &
+                                   parametricCoord, &
+                                   curvatures, &
+                                   ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     api_parametricCoord_, &
+                     api_parametricCoord_n_, &
+                     api_curvatures_, &
+                     api_curvatures_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelGetCurvature")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      real(c_double), dimension(*) :: api_parametricCoord_
+      integer(c_size_t), value, intent(in) :: api_parametricCoord_n_
+      type(c_ptr), intent(out) :: api_curvatures_
+      integer(c_size_t) :: api_curvatures_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    real(c_double), dimension(:), intent(in) :: parametricCoord
+    real(c_double), dimension(:), allocatable, intent(out) :: curvatures
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_curvatures_
+    integer(c_size_t) :: api_curvatures_n_
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         api_parametricCoord_=parametricCoord, &
+         api_parametricCoord_n_=size_gmsh_double(parametricCoord), &
+         api_curvatures_=api_curvatures_, &
+         api_curvatures_n_=api_curvatures_n_, &
+         ierr_=ierr)
+    ! Post processing
+    curvatures = ovectordouble_(api_curvatures_, &
+      api_curvatures_n_)
+  end subroutine gmshModelGetCurvature
+
+  !> Evaluate the principal curvatures of the surface with tag `tag' at the
+  !! parametric coordinates `parametricCoord', as well as their respective
+  !! directions. `parametricCoord' are given by pair of u and v coordinates,
+  !! concatenated: [p1u, p1v, p2u, ...].
+  subroutine gmshModelGetPrincipalCurvatures(tag, &
+                                             parametricCoord, &
+                                             curvatureMax, &
+                                             curvatureMin, &
+                                             directionMax, &
+                                             directionMin, &
+                                             ierr)
+    interface
+    subroutine C_API(tag, &
+                     api_parametricCoord_, &
+                     api_parametricCoord_n_, &
+                     api_curvatureMax_, &
+                     api_curvatureMax_n_, &
+                     api_curvatureMin_, &
+                     api_curvatureMin_n_, &
+                     api_directionMax_, &
+                     api_directionMax_n_, &
+                     api_directionMin_, &
+                     api_directionMin_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelGetPrincipalCurvatures")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      real(c_double), dimension(*) :: api_parametricCoord_
+      integer(c_size_t), value, intent(in) :: api_parametricCoord_n_
+      type(c_ptr), intent(out) :: api_curvatureMax_
+      integer(c_size_t) :: api_curvatureMax_n_
+      type(c_ptr), intent(out) :: api_curvatureMin_
+      integer(c_size_t) :: api_curvatureMin_n_
+      type(c_ptr), intent(out) :: api_directionMax_
+      integer(c_size_t) :: api_directionMax_n_
+      type(c_ptr), intent(out) :: api_directionMin_
+      integer(c_size_t) :: api_directionMin_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    real(c_double), dimension(:), intent(in) :: parametricCoord
+    real(c_double), dimension(:), allocatable, intent(out) :: curvatureMax
+    real(c_double), dimension(:), allocatable, intent(out) :: curvatureMin
+    real(c_double), dimension(:), allocatable, intent(out) :: directionMax
+    real(c_double), dimension(:), allocatable, intent(out) :: directionMin
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_curvatureMax_
+    integer(c_size_t) :: api_curvatureMax_n_
+    type(c_ptr) :: api_curvatureMin_
+    integer(c_size_t) :: api_curvatureMin_n_
+    type(c_ptr) :: api_directionMax_
+    integer(c_size_t) :: api_directionMax_n_
+    type(c_ptr) :: api_directionMin_
+    integer(c_size_t) :: api_directionMin_n_
+    call C_API(tag=int(tag, c_int), &
+         api_parametricCoord_=parametricCoord, &
+         api_parametricCoord_n_=size_gmsh_double(parametricCoord), &
+         api_curvatureMax_=api_curvatureMax_, &
+         api_curvatureMax_n_=api_curvatureMax_n_, &
+         api_curvatureMin_=api_curvatureMin_, &
+         api_curvatureMin_n_=api_curvatureMin_n_, &
+         api_directionMax_=api_directionMax_, &
+         api_directionMax_n_=api_directionMax_n_, &
+         api_directionMin_=api_directionMin_, &
+         api_directionMin_n_=api_directionMin_n_, &
+         ierr_=ierr)
+    ! Post processing
+    curvatureMax = ovectordouble_(api_curvatureMax_, &
+      api_curvatureMax_n_)
+    curvatureMin = ovectordouble_(api_curvatureMin_, &
+      api_curvatureMin_n_)
+    directionMax = ovectordouble_(api_directionMax_, &
+      api_directionMax_n_)
+    directionMin = ovectordouble_(api_directionMin_, &
+      api_directionMin_n_)
+  end subroutine gmshModelGetPrincipalCurvatures
+
+  !> Get the normal to the surface with tag `tag' at the parametric coordinates
+  !! `parametricCoord'. `parametricCoord' are given by pairs of u and v
+  !! coordinates, concatenated: [p1u, p1v, p2u, ...]. `normals' are returned as
+  !! triplets of x, y, z components, concatenated: [n1x, n1y, n1z, n2x, ...].
+  subroutine gmshModelGetNormal(tag, &
+                                parametricCoord, &
+                                normals, &
+                                ierr)
+    interface
+    subroutine C_API(tag, &
+                     api_parametricCoord_, &
+                     api_parametricCoord_n_, &
+                     api_normals_, &
+                     api_normals_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelGetNormal")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      real(c_double), dimension(*) :: api_parametricCoord_
+      integer(c_size_t), value, intent(in) :: api_parametricCoord_n_
+      type(c_ptr), intent(out) :: api_normals_
+      integer(c_size_t) :: api_normals_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    real(c_double), dimension(:), intent(in) :: parametricCoord
+    real(c_double), dimension(:), allocatable, intent(out) :: normals
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_normals_
+    integer(c_size_t) :: api_normals_n_
+    call C_API(tag=int(tag, c_int), &
+         api_parametricCoord_=parametricCoord, &
+         api_parametricCoord_n_=size_gmsh_double(parametricCoord), &
+         api_normals_=api_normals_, &
+         api_normals_n_=api_normals_n_, &
+         ierr_=ierr)
+    ! Post processing
+    normals = ovectordouble_(api_normals_, &
+      api_normals_n_)
+  end subroutine gmshModelGetNormal
+
+  !> Get the parametric coordinates `parametricCoord' for the points `coord' on
+  !! the entity of dimension `dim' and tag `tag'. `coord' are given as triplets
+  !! of x, y, z coordinates, concatenated: [p1x, p1y, p1z, p2x, ...].
+  !! `parametricCoord' returns the parametric coordinates t on the curve (if
+  !! `dim' = 1) or pairs of u and v coordinates concatenated on the surface (if
+  !! `dim' = 2), i.e. [p1t, p2t, ...] or [p1u, p1v, p2u, ...].
+  subroutine gmshModelGetParametrization(dim, &
+                                         tag, &
+                                         coord, &
+                                         parametricCoord, &
+                                         ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     api_coord_, &
+                     api_coord_n_, &
+                     api_parametricCoord_, &
+                     api_parametricCoord_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelGetParametrization")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      real(c_double), dimension(*) :: api_coord_
+      integer(c_size_t), value, intent(in) :: api_coord_n_
+      type(c_ptr), intent(out) :: api_parametricCoord_
+      integer(c_size_t) :: api_parametricCoord_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    real(c_double), dimension(:), intent(in) :: coord
+    real(c_double), dimension(:), allocatable, intent(out) :: parametricCoord
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_parametricCoord_
+    integer(c_size_t) :: api_parametricCoord_n_
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         api_coord_=coord, &
+         api_coord_n_=size_gmsh_double(coord), &
+         api_parametricCoord_=api_parametricCoord_, &
+         api_parametricCoord_n_=api_parametricCoord_n_, &
+         ierr_=ierr)
+    ! Post processing
+    parametricCoord = ovectordouble_(api_parametricCoord_, &
+      api_parametricCoord_n_)
+  end subroutine gmshModelGetParametrization
+
+  !> Get the `min' and `max' bounds of the parametric coordinates for the entity
+  !! of dimension `dim' and tag `tag'.
+  subroutine gmshModelGetParametrizationBounds(dim, &
+                                               tag, &
+                                               min, &
+                                               max, &
+                                               ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     api_min_, &
+                     api_min_n_, &
+                     api_max_, &
+                     api_max_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelGetParametrizationBounds")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      type(c_ptr), intent(out) :: api_min_
+      integer(c_size_t) :: api_min_n_
+      type(c_ptr), intent(out) :: api_max_
+      integer(c_size_t) :: api_max_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    real(c_double), dimension(:), allocatable, intent(out) :: min
+    real(c_double), dimension(:), allocatable, intent(out) :: max
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_min_
+    integer(c_size_t) :: api_min_n_
+    type(c_ptr) :: api_max_
+    integer(c_size_t) :: api_max_n_
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         api_min_=api_min_, &
+         api_min_n_=api_min_n_, &
+         api_max_=api_max_, &
+         api_max_n_=api_max_n_, &
+         ierr_=ierr)
+    ! Post processing
+    min = ovectordouble_(api_min_, &
+      api_min_n_)
+    max = ovectordouble_(api_max_, &
+      api_max_n_)
+  end subroutine gmshModelGetParametrizationBounds
+
+  !> Check if the coordinates (or the parametric coordinates if `parametric' is
+  !! set) provided in `coord' correspond to points inside the entity of
+  !! dimension `dim' and tag `tag', and return the number of points inside. This
+  !! feature is only available for a subset of entities, depending on the
+  !! underlying geometrical representation.
+  function gmshModelIsInside(dim, &
+                             tag, &
+                             coord, &
+                             parametric, &
+                             ierr)
+    interface
+    function C_API(dim, &
+                   tag, &
+                   api_coord_, &
+                   api_coord_n_, &
+                   parametric, &
+                   ierr_) &
+      bind(C, name="gmshModelIsInside")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      real(c_double), dimension(*) :: api_coord_
+      integer(c_size_t), value, intent(in) :: api_coord_n_
+      integer(c_int), value, intent(in) :: parametric
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelIsInside
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    real(c_double), dimension(:), intent(in) :: coord
+    logical, intent(in), optional :: parametric
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelIsInside = C_API(dim=int(dim, c_int), &
+                        tag=int(tag, c_int), &
+                        api_coord_=coord, &
+                        api_coord_n_=size_gmsh_double(coord), &
+                        parametric=optval_c_bool(.false., parametric), &
+                        ierr_=ierr)
+    ! Post processing
+  end function gmshModelIsInside
+
+  !> Get the points `closestCoord' on the entity of dimension `dim' and tag
+  !! `tag' to the points `coord', by orthogonal projection. `coord' and
+  !! `closestCoord' are given as triplets of x, y, z coordinates, concatenated:
+  !! [p1x, p1y, p1z, p2x, ...]. `parametricCoord' returns the parametric
+  !! coordinates t on the curve (if `dim' = 1) or pairs of u and v coordinates
+  !! concatenated on the surface (if `dim' = 2), i.e. [p1t, p2t, ...] or [p1u,
+  !! p1v, p2u, ...].
+  subroutine gmshModelGetClosestPoint(dim, &
+                                      tag, &
+                                      coord, &
+                                      closestCoord, &
+                                      parametricCoord, &
+                                      ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     api_coord_, &
+                     api_coord_n_, &
+                     api_closestCoord_, &
+                     api_closestCoord_n_, &
+                     api_parametricCoord_, &
+                     api_parametricCoord_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelGetClosestPoint")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      real(c_double), dimension(*) :: api_coord_
+      integer(c_size_t), value, intent(in) :: api_coord_n_
+      type(c_ptr), intent(out) :: api_closestCoord_
+      integer(c_size_t) :: api_closestCoord_n_
+      type(c_ptr), intent(out) :: api_parametricCoord_
+      integer(c_size_t) :: api_parametricCoord_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    real(c_double), dimension(:), intent(in) :: coord
+    real(c_double), dimension(:), allocatable, intent(out) :: closestCoord
+    real(c_double), dimension(:), allocatable, intent(out) :: parametricCoord
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_closestCoord_
+    integer(c_size_t) :: api_closestCoord_n_
+    type(c_ptr) :: api_parametricCoord_
+    integer(c_size_t) :: api_parametricCoord_n_
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         api_coord_=coord, &
+         api_coord_n_=size_gmsh_double(coord), &
+         api_closestCoord_=api_closestCoord_, &
+         api_closestCoord_n_=api_closestCoord_n_, &
+         api_parametricCoord_=api_parametricCoord_, &
+         api_parametricCoord_n_=api_parametricCoord_n_, &
+         ierr_=ierr)
+    ! Post processing
+    closestCoord = ovectordouble_(api_closestCoord_, &
+      api_closestCoord_n_)
+    parametricCoord = ovectordouble_(api_parametricCoord_, &
+      api_parametricCoord_n_)
+  end subroutine gmshModelGetClosestPoint
+
+  !> Reparametrize the boundary entity (point or curve, i.e. with `dim' == 0 or
+  !! `dim' == 1) of tag `tag' on the surface `surfaceTag'. If `dim' == 1,
+  !! reparametrize all the points corresponding to the parametric coordinates
+  !! `parametricCoord'. Multiple matches in case of periodic surfaces can be
+  !! selected with `which'. This feature is only available for a subset of
+  !! entities, depending on the underlying geometrical representation.
+  subroutine gmshModelReparametrizeOnSurface(dim, &
+                                             tag, &
+                                             parametricCoord, &
+                                             surfaceTag, &
+                                             surfaceParametricCoord, &
+                                             which, &
+                                             ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     api_parametricCoord_, &
+                     api_parametricCoord_n_, &
+                     surfaceTag, &
+                     api_surfaceParametricCoord_, &
+                     api_surfaceParametricCoord_n_, &
+                     which, &
+                     ierr_) &
+      bind(C, name="gmshModelReparametrizeOnSurface")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      real(c_double), dimension(*) :: api_parametricCoord_
+      integer(c_size_t), value, intent(in) :: api_parametricCoord_n_
+      integer(c_int), value, intent(in) :: surfaceTag
+      type(c_ptr), intent(out) :: api_surfaceParametricCoord_
+      integer(c_size_t) :: api_surfaceParametricCoord_n_
+      integer(c_int), value, intent(in) :: which
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    real(c_double), dimension(:), intent(in) :: parametricCoord
+    integer, intent(in) :: surfaceTag
+    real(c_double), dimension(:), allocatable, intent(out) :: surfaceParametricCoord
+    integer, intent(in), optional :: which
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_surfaceParametricCoord_
+    integer(c_size_t) :: api_surfaceParametricCoord_n_
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         api_parametricCoord_=parametricCoord, &
+         api_parametricCoord_n_=size_gmsh_double(parametricCoord), &
+         surfaceTag=int(surfaceTag, c_int), &
+         api_surfaceParametricCoord_=api_surfaceParametricCoord_, &
+         api_surfaceParametricCoord_n_=api_surfaceParametricCoord_n_, &
+         which=optval_c_int(0, which), &
+         ierr_=ierr)
+    ! Post processing
+    surfaceParametricCoord = ovectordouble_(api_surfaceParametricCoord_, &
+      api_surfaceParametricCoord_n_)
+  end subroutine gmshModelReparametrizeOnSurface
+
+  !> Set the visibility of the model entities `dimTags' to `value'. Apply the
+  !! visibility setting recursively if `recursive' is true.
+  subroutine gmshModelSetVisibility(dimTags, &
+                                    value, &
+                                    recursive, &
+                                    ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     value, &
+                     recursive, &
+                     ierr_) &
+      bind(C, name="gmshModelSetVisibility")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      integer(c_int), value, intent(in) :: value
+      integer(c_int), value, intent(in) :: recursive
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    integer, intent(in) :: value
+    logical, intent(in), optional :: recursive
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         value=int(value, c_int), &
+         recursive=optval_c_bool(.false., recursive), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelSetVisibility
+
+  !> Get the visibility of the model entity of dimension `dim' and tag `tag'.
+  subroutine gmshModelGetVisibility(dim, &
+                                    tag, &
+                                    value, &
+                                    ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     value, &
+                     ierr_) &
+      bind(C, name="gmshModelGetVisibility")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int) :: value
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    integer(c_int) :: value
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         value=value, &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelGetVisibility
+
+  !> Set the global visibility of the model per window to `value', where
+  !! `windowIndex' identifies the window in the window list.
+  subroutine gmshModelSetVisibilityPerWindow(value, &
+                                             windowIndex, &
+                                             ierr)
+    interface
+    subroutine C_API(value, &
+                     windowIndex, &
+                     ierr_) &
+      bind(C, name="gmshModelSetVisibilityPerWindow")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: value
+      integer(c_int), value, intent(in) :: windowIndex
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: value
+    integer, intent(in), optional :: windowIndex
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(value=int(value, c_int), &
+         windowIndex=optval_c_int(0, windowIndex), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelSetVisibilityPerWindow
+
+  !> Set the color of the model entities `dimTags' to the RGBA value (`r', `g',
+  !! `b', `a'), where `r', `g', `b' and `a' should be integers between 0 and
+  !! 255. Apply the color setting recursively if `recursive' is true.
+  subroutine gmshModelSetColor(dimTags, &
+                               r, &
+                               g, &
+                               b, &
+                               a, &
+                               recursive, &
+                               ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     r, &
+                     g, &
+                     b, &
+                     a, &
+                     recursive, &
+                     ierr_) &
+      bind(C, name="gmshModelSetColor")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      integer(c_int), value, intent(in) :: r
+      integer(c_int), value, intent(in) :: g
+      integer(c_int), value, intent(in) :: b
+      integer(c_int), value, intent(in) :: a
+      integer(c_int), value, intent(in) :: recursive
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    integer, intent(in) :: r
+    integer, intent(in) :: g
+    integer, intent(in) :: b
+    integer, intent(in), optional :: a
+    logical, intent(in), optional :: recursive
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         r=int(r, c_int), &
+         g=int(g, c_int), &
+         b=int(b, c_int), &
+         a=optval_c_int(255, a), &
+         recursive=optval_c_bool(.false., recursive), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelSetColor
+
+  !> Get the color of the model entity of dimension `dim' and tag `tag'.
+  subroutine gmshModelGetColor(dim, &
+                               tag, &
+                               r, &
+                               g, &
+                               b, &
+                               a, &
+                               ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     r, &
+                     g, &
+                     b, &
+                     a, &
+                     ierr_) &
+      bind(C, name="gmshModelGetColor")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int) :: r
+      integer(c_int) :: g
+      integer(c_int) :: b
+      integer(c_int) :: a
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    integer(c_int) :: r
+    integer(c_int) :: g
+    integer(c_int) :: b
+    integer(c_int) :: a
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         r=r, &
+         g=g, &
+         b=b, &
+         a=a, &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelGetColor
+
+  !> Set the `x', `y', `z' coordinates of a geometrical point.
+  subroutine gmshModelSetCoordinates(tag, &
+                                     x, &
+                                     y, &
+                                     z, &
+                                     ierr)
+    interface
+    subroutine C_API(tag, &
+                     x, &
+                     y, &
+                     z, &
+                     ierr_) &
+      bind(C, name="gmshModelSetCoordinates")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      real(c_double), value, intent(in) :: x
+      real(c_double), value, intent(in) :: y
+      real(c_double), value, intent(in) :: z
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    real(c_double), intent(in) :: x
+    real(c_double), intent(in) :: y
+    real(c_double), intent(in) :: z
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(tag=int(tag, c_int), &
+         x=real(x, c_double), &
+         y=real(y, c_double), &
+         z=real(z, c_double), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelSetCoordinates
+
+  !> Get the names of any optional attributes stored in the model.
+  subroutine gmshModelGetAttributeNames(names, &
+                                        ierr)
+    interface
+    subroutine C_API(api_names_, &
+                     api_names_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelGetAttributeNames")
+      use, intrinsic :: iso_c_binding
+      type(c_ptr), intent(out) :: api_names_
+      integer(c_size_t), intent(out) :: api_names_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=GMSH_API_MAX_STR_LEN), dimension(:), allocatable, intent(out) :: names
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_names_
+    integer(c_size_t) :: api_names_n_
+    call C_API(api_names_=api_names_, &
+         api_names_n_=api_names_n_, &
+         ierr_=ierr)
+    ! Post processing
+    names = ovectorstring_(api_names_, &
+      api_names_n_)
+  end subroutine gmshModelGetAttributeNames
+
+  !> Get the value of the attribute with name `name'.
+  subroutine gmshModelGetAttribute(name, &
+                                   value, &
+                                   ierr)
+    interface
+    subroutine C_API(name, &
+                     api_value_, &
+                     api_value_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelGetAttribute")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      type(c_ptr), intent(out) :: api_value_
+      integer(c_size_t), intent(out) :: api_value_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: name
+    character(len=GMSH_API_MAX_STR_LEN), dimension(:), allocatable, intent(out) :: value
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_value_
+    integer(c_size_t) :: api_value_n_
+    call C_API(name=istring_(name), &
+         api_value_=api_value_, &
+         api_value_n_=api_value_n_, &
+         ierr_=ierr)
+    ! Post processing
+    value = ovectorstring_(api_value_, &
+      api_value_n_)
+  end subroutine gmshModelGetAttribute
+
+  !> Set the value of the attribute with name `name'.
+  subroutine gmshModelSetAttribute(name, &
+                                   value, &
+                                   ierr)
+    interface
+    subroutine C_API(name, &
+                     api_value_, &
+                     api_value_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelSetAttribute")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      type(c_ptr), dimension(*) :: api_value_
+      integer(c_size_t), value, intent(in) :: api_value_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: name
+    character(len=*), dimension(:), intent(in) :: value
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    character(len=GMSH_API_MAX_STR_LEN, kind=c_char), allocatable :: api_value_strs(:)
+    type(c_ptr), allocatable :: api_value_(:)
+    call ivectorstring_(value, &
+      api_value_strs, &
+      api_value_)
+    call C_API(name=istring_(name), &
+         api_value_=api_value_, &
+         api_value_n_=size_gmsh_str(value), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelSetAttribute
+
+  !> Remove the attribute with name `name'.
+  subroutine gmshModelRemoveAttribute(name, &
+                                      ierr)
+    interface
+    subroutine C_API(name, &
+                     ierr_) &
+      bind(C, name="gmshModelRemoveAttribute")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: name
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(name=istring_(name), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelRemoveAttribute
+
+  !> Generate a mesh of the current model, up to dimension `dim' (0, 1, 2 or 3).
+  subroutine gmshModelMeshGenerate(dim, &
+                                   ierr)
+    interface
+    subroutine C_API(dim, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGenerate")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in), optional :: dim
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=optval_c_int(3, dim), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshGenerate
+
+  !> Partition the mesh of the current model into `numPart' partitions.
+  !! Optionally, `elementTags' and `partitions' can be provided to specify the
+  !! partition of each element explicitly.
+  subroutine gmshModelMeshPartition(numPart, &
+                                    elementTags, &
+                                    partitions, &
+                                    ierr)
+    interface
+    subroutine C_API(numPart, &
+                     api_elementTags_, &
+                     api_elementTags_n_, &
+                     api_partitions_, &
+                     api_partitions_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshPartition")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: numPart
+      integer(c_size_t), dimension(*), optional :: api_elementTags_
+      integer(c_size_t), value, intent(in) :: api_elementTags_n_
+      integer(c_int), dimension(*), optional :: api_partitions_
+      integer(c_size_t), value, intent(in) :: api_partitions_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: numPart
+    integer(c_size_t), dimension(:), intent(in), optional :: elementTags
+    integer(c_int), dimension(:), intent(in), optional :: partitions
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(numPart=int(numPart, c_int), &
+         api_elementTags_=elementTags, &
+         api_elementTags_n_=size_gmsh_size(elementTags), &
+         api_partitions_=partitions, &
+         api_partitions_n_=size_gmsh_int(partitions), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshPartition
+
+  !> Unpartition the mesh of the current model.
+  subroutine gmshModelMeshUnpartition(ierr)
+    interface
+    subroutine C_API(ierr_) &
+      bind(C, name="gmshModelMeshUnpartition")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshUnpartition
+
+  !> Optimize the mesh of the current model using `method' (empty for default
+  !! tetrahedral mesh optimizer, "Netgen" for Netgen optimizer, "HighOrder" for
+  !! direct high-order mesh optimizer, "HighOrderElastic" for high-order elastic
+  !! smoother, "HighOrderFastCurving" for fast curving algorithm, "Laplace2D"
+  !! for Laplace smoothing, "Relocate2D" and "Relocate3D" for node relocation,
+  !! "QuadQuasiStructured" for quad mesh optimization, "UntangleMeshGeometry"
+  !! for untangling). If `force' is set apply the optimization also to discrete
+  !! entities. If `dimTags' is given, only apply the optimizer to the given
+  !! entities.
+  subroutine gmshModelMeshOptimize(method, &
+                                   force, &
+                                   niter, &
+                                   dimTags, &
+                                   ierr)
+    interface
+    subroutine C_API(method, &
+                     force, &
+                     niter, &
+                     api_dimTags_, &
+                     api_dimTags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshOptimize")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in), optional :: method
+      integer(c_int), value, intent(in) :: force
+      integer(c_int), value, intent(in) :: niter
+      integer(c_int), dimension(*), optional :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in), optional :: method
+    logical, intent(in), optional :: force
+    integer, intent(in), optional :: niter
+    integer(c_int), dimension(:,:), intent(in), optional :: dimTags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(method=istring_(optval_c_str("", method)), &
+         force=optval_c_bool(.false., force), &
+         niter=optval_c_int(1, niter), &
+         api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshOptimize
+
+  !> Recombine the mesh of the current model.
+  subroutine gmshModelMeshRecombine(ierr)
+    interface
+    subroutine C_API(ierr_) &
+      bind(C, name="gmshModelMeshRecombine")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshRecombine
+
+  !> Refine the mesh of the current model by uniformly splitting the elements.
+  subroutine gmshModelMeshRefine(ierr)
+    interface
+    subroutine C_API(ierr_) &
+      bind(C, name="gmshModelMeshRefine")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshRefine
+
+  !> Set the order of the elements in the mesh of the current model to `order'.
+  subroutine gmshModelMeshSetOrder(order, &
+                                   ierr)
+    interface
+    subroutine C_API(order, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshSetOrder")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: order
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: order
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(order=int(order, c_int), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshSetOrder
+
+  !> Get the last entities (if any) where a meshing error occurred. Currently
+  !! only populated by the new 3D meshing algorithms.
+  subroutine gmshModelMeshGetLastEntityError(dimTags, &
+                                             ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetLastEntityError")
+      use, intrinsic :: iso_c_binding
+      type(c_ptr), intent(out) :: api_dimTags_
+      integer(c_size_t), intent(out) :: api_dimTags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: dimTags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_dimTags_
+    integer(c_size_t) :: api_dimTags_n_
+    call C_API(api_dimTags_=api_dimTags_, &
+         api_dimTags_n_=api_dimTags_n_, &
+         ierr_=ierr)
+    ! Post processing
+    dimTags = ovectorpair_(api_dimTags_, &
+      api_dimTags_n_)
+  end subroutine gmshModelMeshGetLastEntityError
+
+  !> Get the last nodes (if any) where a meshing error occurred. Currently only
+  !! populated by the new 3D meshing algorithms.
+  subroutine gmshModelMeshGetLastNodeError(nodeTags, &
+                                           ierr)
+    interface
+    subroutine C_API(api_nodeTags_, &
+                     api_nodeTags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetLastNodeError")
+      use, intrinsic :: iso_c_binding
+      type(c_ptr), intent(out) :: api_nodeTags_
+      integer(c_size_t), intent(out) :: api_nodeTags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: nodeTags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_nodeTags_
+    integer(c_size_t) :: api_nodeTags_n_
+    call C_API(api_nodeTags_=api_nodeTags_, &
+         api_nodeTags_n_=api_nodeTags_n_, &
+         ierr_=ierr)
+    ! Post processing
+    nodeTags = ovectorsize_(api_nodeTags_, &
+      api_nodeTags_n_)
+  end subroutine gmshModelMeshGetLastNodeError
+
+  !> Clear the mesh, i.e. delete all the nodes and elements, for the entities
+  !! `dimTags'. If `dimTags' is empty, clear the whole mesh. Note that the mesh
+  !! of an entity can only be cleared if this entity is not on the boundary of
+  !! another entity with a non-empty mesh.
+  subroutine gmshModelMeshClear(dimTags, &
+                                ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshClear")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*), optional :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in), optional :: dimTags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshClear
+
+  !> Reverse the orientation of the elements in the entities `dimTags'. If
+  !! `dimTags' is empty, reverse the orientation of the elements in the whole
+  !! mesh.
+  subroutine gmshModelMeshReverse(dimTags, &
+                                  ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshReverse")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*), optional :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in), optional :: dimTags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshReverse
+
+  !> Apply the affine transformation `affineTransform' (16 entries of a 4x4
+  !! matrix, by row; only the 12 first can be provided for convenience) to the
+  !! coordinates of the nodes classified on the entities `dimTags'. If `dimTags'
+  !! is empty, transform all the nodes in the mesh.
+  subroutine gmshModelMeshAffineTransform(affineTransform, &
+                                          dimTags, &
+                                          ierr)
+    interface
+    subroutine C_API(api_affineTransform_, &
+                     api_affineTransform_n_, &
+                     api_dimTags_, &
+                     api_dimTags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshAffineTransform")
+      use, intrinsic :: iso_c_binding
+      real(c_double), dimension(*) :: api_affineTransform_
+      integer(c_size_t), value, intent(in) :: api_affineTransform_n_
+      integer(c_int), dimension(*), optional :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    real(c_double), dimension(:), intent(in) :: affineTransform
+    integer(c_int), dimension(:,:), intent(in), optional :: dimTags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_affineTransform_=affineTransform, &
+         api_affineTransform_n_=size_gmsh_double(affineTransform), &
+         api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshAffineTransform
+
+  !> 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).
+  subroutine gmshModelMeshGetNodes(nodeTags, &
+                                   coord, &
+                                   parametricCoord, &
+                                   dim, &
+                                   tag, &
+                                   includeBoundary, &
+                                   returnParametricCoord, &
+                                   ierr)
+    interface
+    subroutine C_API(api_nodeTags_, &
+                     api_nodeTags_n_, &
+                     api_coord_, &
+                     api_coord_n_, &
+                     api_parametricCoord_, &
+                     api_parametricCoord_n_, &
+                     dim, &
+                     tag, &
+                     includeBoundary, &
+                     returnParametricCoord, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetNodes")
+      use, intrinsic :: iso_c_binding
+      type(c_ptr), intent(out) :: api_nodeTags_
+      integer(c_size_t), intent(out) :: api_nodeTags_n_
+      type(c_ptr), intent(out) :: api_coord_
+      integer(c_size_t) :: api_coord_n_
+      type(c_ptr), intent(out) :: api_parametricCoord_
+      integer(c_size_t) :: api_parametricCoord_n_
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: includeBoundary
+      integer(c_int), value, intent(in) :: returnParametricCoord
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: nodeTags
+    real(c_double), dimension(:), allocatable, intent(out) :: coord
+    real(c_double), dimension(:), allocatable, intent(out) :: parametricCoord
+    integer, intent(in), optional :: dim
+    integer, intent(in), optional :: tag
+    logical, intent(in), optional :: includeBoundary
+    logical, intent(in), optional :: returnParametricCoord
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_nodeTags_
+    integer(c_size_t) :: api_nodeTags_n_
+    type(c_ptr) :: api_coord_
+    integer(c_size_t) :: api_coord_n_
+    type(c_ptr) :: api_parametricCoord_
+    integer(c_size_t) :: api_parametricCoord_n_
+    call C_API(api_nodeTags_=api_nodeTags_, &
+         api_nodeTags_n_=api_nodeTags_n_, &
+         api_coord_=api_coord_, &
+         api_coord_n_=api_coord_n_, &
+         api_parametricCoord_=api_parametricCoord_, &
+         api_parametricCoord_n_=api_parametricCoord_n_, &
+         dim=optval_c_int(-1, dim), &
+         tag=optval_c_int(-1, tag), &
+         includeBoundary=optval_c_bool(.false., includeBoundary), &
+         returnParametricCoord=optval_c_bool(.true., returnParametricCoord), &
+         ierr_=ierr)
+    ! Post processing
+    nodeTags = ovectorsize_(api_nodeTags_, &
+      api_nodeTags_n_)
+    coord = ovectordouble_(api_coord_, &
+      api_coord_n_)
+    parametricCoord = ovectordouble_(api_parametricCoord_, &
+      api_parametricCoord_n_)
+  end subroutine gmshModelMeshGetNodes
+
+  !> Get the nodes classified on the entity of tag `tag', for all the elements
+  !! of type `elementType'. The other arguments are treated as in `getNodes'.
+  subroutine gmshModelMeshGetNodesByElementType(elementType, &
+                                                nodeTags, &
+                                                coord, &
+                                                parametricCoord, &
+                                                tag, &
+                                                returnParametricCoord, &
+                                                ierr)
+    interface
+    subroutine C_API(elementType, &
+                     api_nodeTags_, &
+                     api_nodeTags_n_, &
+                     api_coord_, &
+                     api_coord_n_, &
+                     api_parametricCoord_, &
+                     api_parametricCoord_n_, &
+                     tag, &
+                     returnParametricCoord, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetNodesByElementType")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: elementType
+      type(c_ptr), intent(out) :: api_nodeTags_
+      integer(c_size_t), intent(out) :: api_nodeTags_n_
+      type(c_ptr), intent(out) :: api_coord_
+      integer(c_size_t) :: api_coord_n_
+      type(c_ptr), intent(out) :: api_parametricCoord_
+      integer(c_size_t) :: api_parametricCoord_n_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: returnParametricCoord
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: elementType
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: nodeTags
+    real(c_double), dimension(:), allocatable, intent(out) :: coord
+    real(c_double), dimension(:), allocatable, intent(out) :: parametricCoord
+    integer, intent(in), optional :: tag
+    logical, intent(in), optional :: returnParametricCoord
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_nodeTags_
+    integer(c_size_t) :: api_nodeTags_n_
+    type(c_ptr) :: api_coord_
+    integer(c_size_t) :: api_coord_n_
+    type(c_ptr) :: api_parametricCoord_
+    integer(c_size_t) :: api_parametricCoord_n_
+    call C_API(elementType=int(elementType, c_int), &
+         api_nodeTags_=api_nodeTags_, &
+         api_nodeTags_n_=api_nodeTags_n_, &
+         api_coord_=api_coord_, &
+         api_coord_n_=api_coord_n_, &
+         api_parametricCoord_=api_parametricCoord_, &
+         api_parametricCoord_n_=api_parametricCoord_n_, &
+         tag=optval_c_int(-1, tag), &
+         returnParametricCoord=optval_c_bool(.true., returnParametricCoord), &
+         ierr_=ierr)
+    ! Post processing
+    nodeTags = ovectorsize_(api_nodeTags_, &
+      api_nodeTags_n_)
+    coord = ovectordouble_(api_coord_, &
+      api_coord_n_)
+    parametricCoord = ovectordouble_(api_parametricCoord_, &
+      api_parametricCoord_n_)
+  end subroutine gmshModelMeshGetNodesByElementType
+
+  !> Get the coordinates and the parametric coordinates (if any) of the node
+  !! with tag `tag', as well as the dimension `dim' and tag `tag' of the entity
+  !! on which the node is classified. This function relies on an internal cache
+  !! (a vector in case of dense node numbering, a map otherwise); for large
+  !! meshes accessing nodes in bulk is often preferable.
+  subroutine gmshModelMeshGetNode(nodeTag, &
+                                  coord, &
+                                  parametricCoord, &
+                                  dim, &
+                                  tag, &
+                                  ierr)
+    interface
+    subroutine C_API(nodeTag, &
+                     api_coord_, &
+                     api_coord_n_, &
+                     api_parametricCoord_, &
+                     api_parametricCoord_n_, &
+                     dim, &
+                     tag, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetNode")
+      use, intrinsic :: iso_c_binding
+      integer(c_size_t), value, intent(in) :: nodeTag
+      type(c_ptr), intent(out) :: api_coord_
+      integer(c_size_t) :: api_coord_n_
+      type(c_ptr), intent(out) :: api_parametricCoord_
+      integer(c_size_t) :: api_parametricCoord_n_
+      integer(c_int) :: dim
+      integer(c_int) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: nodeTag
+    real(c_double), dimension(:), allocatable, intent(out) :: coord
+    real(c_double), dimension(:), allocatable, intent(out) :: parametricCoord
+    integer(c_int) :: dim
+    integer(c_int) :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_coord_
+    integer(c_size_t) :: api_coord_n_
+    type(c_ptr) :: api_parametricCoord_
+    integer(c_size_t) :: api_parametricCoord_n_
+    call C_API(nodeTag=int(nodeTag, c_size_t), &
+         api_coord_=api_coord_, &
+         api_coord_n_=api_coord_n_, &
+         api_parametricCoord_=api_parametricCoord_, &
+         api_parametricCoord_n_=api_parametricCoord_n_, &
+         dim=dim, &
+         tag=tag, &
+         ierr_=ierr)
+    ! Post processing
+    coord = ovectordouble_(api_coord_, &
+      api_coord_n_)
+    parametricCoord = ovectordouble_(api_parametricCoord_, &
+      api_parametricCoord_n_)
+  end subroutine gmshModelMeshGetNode
+
+  !> Set the coordinates and the parametric coordinates (if any) of the node
+  !! with tag `tag'. This function relies on an internal cache (a vector in case
+  !! of dense node numbering, a map otherwise); for large meshes accessing nodes
+  !! in bulk is often preferable.
+  subroutine gmshModelMeshSetNode(nodeTag, &
+                                  coord, &
+                                  parametricCoord, &
+                                  ierr)
+    interface
+    subroutine C_API(nodeTag, &
+                     api_coord_, &
+                     api_coord_n_, &
+                     api_parametricCoord_, &
+                     api_parametricCoord_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshSetNode")
+      use, intrinsic :: iso_c_binding
+      integer(c_size_t), value, intent(in) :: nodeTag
+      real(c_double), dimension(*) :: api_coord_
+      integer(c_size_t), value, intent(in) :: api_coord_n_
+      real(c_double), dimension(*) :: api_parametricCoord_
+      integer(c_size_t), value, intent(in) :: api_parametricCoord_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: nodeTag
+    real(c_double), dimension(:), intent(in) :: coord
+    real(c_double), dimension(:), intent(in) :: parametricCoord
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(nodeTag=int(nodeTag, c_size_t), &
+         api_coord_=coord, &
+         api_coord_n_=size_gmsh_double(coord), &
+         api_parametricCoord_=parametricCoord, &
+         api_parametricCoord_n_=size_gmsh_double(parametricCoord), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshSetNode
+
+  !> Rebuild the node cache.
+  subroutine gmshModelMeshRebuildNodeCache(onlyIfNecessary, &
+                                           ierr)
+    interface
+    subroutine C_API(onlyIfNecessary, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshRebuildNodeCache")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: onlyIfNecessary
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    logical, intent(in), optional :: onlyIfNecessary
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(onlyIfNecessary=optval_c_bool(.true., onlyIfNecessary), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshRebuildNodeCache
+
+  !> Rebuild the element cache.
+  subroutine gmshModelMeshRebuildElementCache(onlyIfNecessary, &
+                                              ierr)
+    interface
+    subroutine C_API(onlyIfNecessary, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshRebuildElementCache")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: onlyIfNecessary
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    logical, intent(in), optional :: onlyIfNecessary
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(onlyIfNecessary=optval_c_bool(.true., onlyIfNecessary), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshRebuildElementCache
+
+  !> 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, ...].
+  subroutine gmshModelMeshGetNodesForPhysicalGroup(dim, &
+                                                   tag, &
+                                                   nodeTags, &
+                                                   coord, &
+                                                   ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     api_nodeTags_, &
+                     api_nodeTags_n_, &
+                     api_coord_, &
+                     api_coord_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetNodesForPhysicalGroup")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      type(c_ptr), intent(out) :: api_nodeTags_
+      integer(c_size_t), intent(out) :: api_nodeTags_n_
+      type(c_ptr), intent(out) :: api_coord_
+      integer(c_size_t) :: api_coord_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: nodeTags
+    real(c_double), dimension(:), allocatable, intent(out) :: coord
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_nodeTags_
+    integer(c_size_t) :: api_nodeTags_n_
+    type(c_ptr) :: api_coord_
+    integer(c_size_t) :: api_coord_n_
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         api_nodeTags_=api_nodeTags_, &
+         api_nodeTags_n_=api_nodeTags_n_, &
+         api_coord_=api_coord_, &
+         api_coord_n_=api_coord_n_, &
+         ierr_=ierr)
+    ! Post processing
+    nodeTags = ovectorsize_(api_nodeTags_, &
+      api_nodeTags_n_)
+    coord = ovectordouble_(api_coord_, &
+      api_coord_n_)
+  end subroutine gmshModelMeshGetNodesForPhysicalGroup
+
+  !> Get the maximum tag `maxTag' of a node in the mesh.
+  subroutine gmshModelMeshGetMaxNodeTag(maxTag, &
+                                        ierr)
+    interface
+    subroutine C_API(maxTag, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetMaxNodeTag")
+      use, intrinsic :: iso_c_binding
+      integer(c_size_t) :: maxTag
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_size_t) :: maxTag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(maxTag=maxTag, &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshGetMaxNodeTag
+
+  !> 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.
+  subroutine gmshModelMeshAddNodes(dim, &
+                                   tag, &
+                                   nodeTags, &
+                                   coord, &
+                                   parametricCoord, &
+                                   ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     api_nodeTags_, &
+                     api_nodeTags_n_, &
+                     api_coord_, &
+                     api_coord_n_, &
+                     api_parametricCoord_, &
+                     api_parametricCoord_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshAddNodes")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      integer(c_size_t), dimension(*) :: api_nodeTags_
+      integer(c_size_t), value, intent(in) :: api_nodeTags_n_
+      real(c_double), dimension(*) :: api_coord_
+      integer(c_size_t), value, intent(in) :: api_coord_n_
+      real(c_double), dimension(*), optional :: api_parametricCoord_
+      integer(c_size_t), value, intent(in) :: api_parametricCoord_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    integer(c_size_t), dimension(:), intent(in) :: nodeTags
+    real(c_double), dimension(:), intent(in) :: coord
+    real(c_double), dimension(:), intent(in), optional :: parametricCoord
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         api_nodeTags_=nodeTags, &
+         api_nodeTags_n_=size_gmsh_size(nodeTags), &
+         api_coord_=coord, &
+         api_coord_n_=size_gmsh_double(coord), &
+         api_parametricCoord_=parametricCoord, &
+         api_parametricCoord_n_=size_gmsh_double(parametricCoord), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshAddNodes
+
+  !> 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.
+  subroutine gmshModelMeshReclassifyNodes(ierr)
+    interface
+    subroutine C_API(ierr_) &
+      bind(C, name="gmshModelMeshReclassifyNodes")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshReclassifyNodes
+
+  !> Relocate the nodes classified on the entity of dimension `dim' and tag
+  !! `tag' using their parametric coordinates. If `tag' < 0, relocate the nodes
+  !! for all entities of dimension `dim'. If `dim' and `tag' are negative,
+  !! relocate all the nodes in the mesh.
+  subroutine gmshModelMeshRelocateNodes(dim, &
+                                        tag, &
+                                        ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshRelocateNodes")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in), optional :: dim
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=optval_c_int(-1, dim), &
+         tag=optval_c_int(-1, tag), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshRelocateNodes
+
+  !> Get the elements classified on the entity of dimension `dim' and tag `tag'.
+  !! If `tag' < 0, get the elements for all entities of dimension `dim'. If
+  !! `dim' and `tag' are negative, get all the elements in the mesh.
+  !! `elementTypes' contains the MSH types of the elements (e.g. `2' for 3-node
+  !! triangles: see `getElementProperties' to obtain the properties for a given
+  !! element type). `elementTags' is a vector of the same length as
+  !! `elementTypes'; 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 `elementTypes'; each
+  !! entry is a vector of length equal to the number of elements of the given
+  !! type times the number N of nodes for this type of element, that contains
+  !! the node tags of all the elements of the given type, concatenated: [e1n1,
+  !! e1n2, ..., e1nN, e2n1, ...].
+  subroutine gmshModelMeshGetElements(elementTypes, &
+                                      elementTags, &
+                                      elementTags_n, &
+                                      nodeTags, &
+                                      nodeTags_n, &
+                                      dim, &
+                                      tag, &
+                                      ierr)
+    interface
+    subroutine C_API(api_elementTypes_, &
+                     api_elementTypes_n_, &
+                     api_elementTags_, &
+                     api_elementTags_n_, &
+                     api_elementTags_nn_, &
+                     api_nodeTags_, &
+                     api_nodeTags_n_, &
+                     api_nodeTags_nn_, &
+                     dim, &
+                     tag, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetElements")
+      use, intrinsic :: iso_c_binding
+      type(c_ptr), intent(out) :: api_elementTypes_
+      integer(c_size_t), intent(out) :: api_elementTypes_n_
+      type(c_ptr), intent(out) :: api_elementTags_
+      type(c_ptr), intent(out) :: api_elementTags_n_
+      integer(c_size_t), intent(out) :: api_elementTags_nn_
+      type(c_ptr), intent(out) :: api_nodeTags_
+      type(c_ptr), intent(out) :: api_nodeTags_n_
+      integer(c_size_t), intent(out) :: api_nodeTags_nn_
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:), allocatable, intent(out) :: elementTypes
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: elementTags
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: elementTags_n
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: nodeTags
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: nodeTags_n
+    integer, intent(in), optional :: dim
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_elementTypes_
+    integer(c_size_t) :: api_elementTypes_n_
+    type(c_ptr) :: api_elementTags_, api_elementTags_n_
+    integer(c_size_t) :: api_elementTags_nn_
+    type(c_ptr) :: api_nodeTags_, api_nodeTags_n_
+    integer(c_size_t) :: api_nodeTags_nn_
+    call C_API(api_elementTypes_=api_elementTypes_, &
+         api_elementTypes_n_=api_elementTypes_n_, &
+         api_elementTags_=api_elementTags_, &
+         api_elementTags_n_=api_elementTags_n_, &
+         api_elementTags_nn_=api_elementTags_nn_, &
+         api_nodeTags_=api_nodeTags_, &
+         api_nodeTags_n_=api_nodeTags_n_, &
+         api_nodeTags_nn_=api_nodeTags_nn_, &
+         dim=optval_c_int(-1, dim), &
+         tag=optval_c_int(-1, tag), &
+         ierr_=ierr)
+    ! Post processing
+    elementTypes = ovectorint_(api_elementTypes_, &
+      api_elementTypes_n_)
+    call ovectorvectorsize_(api_elementTags_, &
+      api_elementTags_n_, &
+      api_elementTags_nn_, &
+      elementTags, &
+      elementTags_n)
+    call ovectorvectorsize_(api_nodeTags_, &
+      api_nodeTags_n_, &
+      api_nodeTags_nn_, &
+      nodeTags, &
+      nodeTags_n)
+  end subroutine gmshModelMeshGetElements
+
+  !> Get the type and node tags of the element with tag `tag', as well as the
+  !! dimension `dim' and tag `tag' of the entity on which the element is
+  !! classified. This function relies on an internal cache (a vector in case of
+  !! dense element numbering, a map otherwise); for large meshes accessing
+  !! elements in bulk is often preferable.
+  subroutine gmshModelMeshGetElement(elementTag, &
+                                     elementType, &
+                                     nodeTags, &
+                                     dim, &
+                                     tag, &
+                                     ierr)
+    interface
+    subroutine C_API(elementTag, &
+                     elementType, &
+                     api_nodeTags_, &
+                     api_nodeTags_n_, &
+                     dim, &
+                     tag, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetElement")
+      use, intrinsic :: iso_c_binding
+      integer(c_size_t), value, intent(in) :: elementTag
+      integer(c_int) :: elementType
+      type(c_ptr), intent(out) :: api_nodeTags_
+      integer(c_size_t), intent(out) :: api_nodeTags_n_
+      integer(c_int) :: dim
+      integer(c_int) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: elementTag
+    integer(c_int) :: elementType
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: nodeTags
+    integer(c_int) :: dim
+    integer(c_int) :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_nodeTags_
+    integer(c_size_t) :: api_nodeTags_n_
+    call C_API(elementTag=int(elementTag, c_size_t), &
+         elementType=elementType, &
+         api_nodeTags_=api_nodeTags_, &
+         api_nodeTags_n_=api_nodeTags_n_, &
+         dim=dim, &
+         tag=tag, &
+         ierr_=ierr)
+    ! Post processing
+    nodeTags = ovectorsize_(api_nodeTags_, &
+      api_nodeTags_n_)
+  end subroutine gmshModelMeshGetElement
+
+  !> Search the mesh for an element located at coordinates (`x', `y', `z'). This
+  !! function performs a search in a spatial octree. If an element is found,
+  !! return its tag, type and node tags, as well as the local coordinates (`u',
+  !! `v', `w') within the reference element corresponding to search location. If
+  !! `dim' is >= 0, only search for elements of the given dimension. If `strict'
+  !! is not set, use a tolerance to find elements near the search location.
+  subroutine gmshModelMeshGetElementByCoordinates(x, &
+                                                  y, &
+                                                  z, &
+                                                  elementTag, &
+                                                  elementType, &
+                                                  nodeTags, &
+                                                  u, &
+                                                  v, &
+                                                  w, &
+                                                  dim, &
+                                                  strict, &
+                                                  ierr)
+    interface
+    subroutine C_API(x, &
+                     y, &
+                     z, &
+                     elementTag, &
+                     elementType, &
+                     api_nodeTags_, &
+                     api_nodeTags_n_, &
+                     u, &
+                     v, &
+                     w, &
+                     dim, &
+                     strict, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetElementByCoordinates")
+      use, intrinsic :: iso_c_binding
+      real(c_double), value, intent(in) :: x
+      real(c_double), value, intent(in) :: y
+      real(c_double), value, intent(in) :: z
+      integer(c_size_t) :: elementTag
+      integer(c_int) :: elementType
+      type(c_ptr), intent(out) :: api_nodeTags_
+      integer(c_size_t), intent(out) :: api_nodeTags_n_
+      real(c_double) :: u
+      real(c_double) :: v
+      real(c_double) :: w
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: strict
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    real(c_double), intent(in) :: x
+    real(c_double), intent(in) :: y
+    real(c_double), intent(in) :: z
+    integer(c_size_t) :: elementTag
+    integer(c_int) :: elementType
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: nodeTags
+    real(c_double) :: u
+    real(c_double) :: v
+    real(c_double) :: w
+    integer, intent(in), optional :: dim
+    logical, intent(in), optional :: strict
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_nodeTags_
+    integer(c_size_t) :: api_nodeTags_n_
+    call C_API(x=real(x, c_double), &
+         y=real(y, c_double), &
+         z=real(z, c_double), &
+         elementTag=elementTag, &
+         elementType=elementType, &
+         api_nodeTags_=api_nodeTags_, &
+         api_nodeTags_n_=api_nodeTags_n_, &
+         u=u, &
+         v=v, &
+         w=w, &
+         dim=optval_c_int(-1, dim), &
+         strict=optval_c_bool(.false., strict), &
+         ierr_=ierr)
+    ! Post processing
+    nodeTags = ovectorsize_(api_nodeTags_, &
+      api_nodeTags_n_)
+  end subroutine gmshModelMeshGetElementByCoordinates
+
+  !> Search the mesh for element(s) located at coordinates (`x', `y', `z'). This
+  !! function performs a search in a spatial octree. Return the tags of all
+  !! found elements in `elementTags'. Additional information about the elements
+  !! can be accessed through `getElement' and `getLocalCoordinatesInElement'. If
+  !! `dim' is >= 0, only search for elements of the given dimension. If `strict'
+  !! is not set, use a tolerance to find elements near the search location.
+  subroutine gmshModelMeshGetElementsByCoordinates(x, &
+                                                   y, &
+                                                   z, &
+                                                   elementTags, &
+                                                   dim, &
+                                                   strict, &
+                                                   ierr)
+    interface
+    subroutine C_API(x, &
+                     y, &
+                     z, &
+                     api_elementTags_, &
+                     api_elementTags_n_, &
+                     dim, &
+                     strict, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetElementsByCoordinates")
+      use, intrinsic :: iso_c_binding
+      real(c_double), value, intent(in) :: x
+      real(c_double), value, intent(in) :: y
+      real(c_double), value, intent(in) :: z
+      type(c_ptr), intent(out) :: api_elementTags_
+      integer(c_size_t), intent(out) :: api_elementTags_n_
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: strict
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    real(c_double), intent(in) :: x
+    real(c_double), intent(in) :: y
+    real(c_double), intent(in) :: z
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: elementTags
+    integer, intent(in), optional :: dim
+    logical, intent(in), optional :: strict
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_elementTags_
+    integer(c_size_t) :: api_elementTags_n_
+    call C_API(x=real(x, c_double), &
+         y=real(y, c_double), &
+         z=real(z, c_double), &
+         api_elementTags_=api_elementTags_, &
+         api_elementTags_n_=api_elementTags_n_, &
+         dim=optval_c_int(-1, dim), &
+         strict=optval_c_bool(.false., strict), &
+         ierr_=ierr)
+    ! Post processing
+    elementTags = ovectorsize_(api_elementTags_, &
+      api_elementTags_n_)
+  end subroutine gmshModelMeshGetElementsByCoordinates
+
+  !> Return the local coordinates (`u', `v', `w') within the element
+  !! `elementTag' corresponding to the model coordinates (`x', `y', `z'). This
+  !! function relies on an internal cache (a vector in case of dense element
+  !! numbering, a map otherwise); for large meshes accessing elements in bulk is
+  !! often preferable.
+  subroutine gmshModelMeshGetLocalCoordinatesInElement(elementTag, &
+                                                       x, &
+                                                       y, &
+                                                       z, &
+                                                       u, &
+                                                       v, &
+                                                       w, &
+                                                       ierr)
+    interface
+    subroutine C_API(elementTag, &
+                     x, &
+                     y, &
+                     z, &
+                     u, &
+                     v, &
+                     w, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetLocalCoordinatesInElement")
+      use, intrinsic :: iso_c_binding
+      integer(c_size_t), value, intent(in) :: elementTag
+      real(c_double), value, intent(in) :: x
+      real(c_double), value, intent(in) :: y
+      real(c_double), value, intent(in) :: z
+      real(c_double) :: u
+      real(c_double) :: v
+      real(c_double) :: w
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: elementTag
+    real(c_double), intent(in) :: x
+    real(c_double), intent(in) :: y
+    real(c_double), intent(in) :: z
+    real(c_double) :: u
+    real(c_double) :: v
+    real(c_double) :: w
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(elementTag=int(elementTag, c_size_t), &
+         x=real(x, c_double), &
+         y=real(y, c_double), &
+         z=real(z, c_double), &
+         u=u, &
+         v=v, &
+         w=w, &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshGetLocalCoordinatesInElement
+
+  !> Get the types of elements in the entity of dimension `dim' and tag `tag'.
+  !! If `tag' < 0, get the types for all entities of dimension `dim'. If `dim'
+  !! and `tag' are negative, get all the types in the mesh.
+  subroutine gmshModelMeshGetElementTypes(elementTypes, &
+                                          dim, &
+                                          tag, &
+                                          ierr)
+    interface
+    subroutine C_API(api_elementTypes_, &
+                     api_elementTypes_n_, &
+                     dim, &
+                     tag, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetElementTypes")
+      use, intrinsic :: iso_c_binding
+      type(c_ptr), intent(out) :: api_elementTypes_
+      integer(c_size_t), intent(out) :: api_elementTypes_n_
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:), allocatable, intent(out) :: elementTypes
+    integer, intent(in), optional :: dim
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_elementTypes_
+    integer(c_size_t) :: api_elementTypes_n_
+    call C_API(api_elementTypes_=api_elementTypes_, &
+         api_elementTypes_n_=api_elementTypes_n_, &
+         dim=optval_c_int(-1, dim), &
+         tag=optval_c_int(-1, tag), &
+         ierr_=ierr)
+    ! Post processing
+    elementTypes = ovectorint_(api_elementTypes_, &
+      api_elementTypes_n_)
+  end subroutine gmshModelMeshGetElementTypes
+
+  !> Return an element type given its family name `familyName' ("Point", "Line",
+  !! "Triangle", "Quadrangle", "Tetrahedron", "Pyramid", "Prism", "Hexahedron")
+  !! and polynomial order `order'. If `serendip' is true, return the
+  !! corresponding serendip element type (element without interior nodes).
+  function gmshModelMeshGetElementType(familyName, &
+                                       order, &
+                                       serendip, &
+                                       ierr)
+    interface
+    function C_API(familyName, &
+                   order, &
+                   serendip, &
+                   ierr_) &
+      bind(C, name="gmshModelMeshGetElementType")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      character(len=1, kind=c_char), dimension(*), intent(in) :: familyName
+      integer(c_int), value, intent(in) :: order
+      integer(c_int), value, intent(in) :: serendip
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelMeshGetElementType
+    character(len=*), intent(in) :: familyName
+    integer, intent(in) :: order
+    logical, intent(in), optional :: serendip
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelMeshGetElementType = C_API(familyName=istring_(familyName), &
+                                  order=int(order, c_int), &
+                                  serendip=optval_c_bool(.false., serendip), &
+                                  ierr_=ierr)
+    ! Post processing
+  end function gmshModelMeshGetElementType
+
+  !> Get the properties of an element of type `elementType': its name
+  !! (`elementName'), dimension (`dim'), order (`order'), number of nodes
+  !! (`numNodes'), local coordinates of the nodes in the reference element
+  !! (`localNodeCoord' vector, of length `dim' times `numNodes') and number of
+  !! primary (first order) nodes (`numPrimaryNodes').
+  subroutine gmshModelMeshGetElementProperties(elementType, &
+                                               elementName, &
+                                               dim, &
+                                               order, &
+                                               numNodes, &
+                                               localNodeCoord, &
+                                               numPrimaryNodes, &
+                                               ierr)
+    interface
+    subroutine C_API(elementType, &
+                     api_elementName_, &
+                     dim, &
+                     order, &
+                     numNodes, &
+                     api_localNodeCoord_, &
+                     api_localNodeCoord_n_, &
+                     numPrimaryNodes, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetElementProperties")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: elementType
+      character(kind=c_char), dimension(*) :: api_elementName_
+      integer(c_int) :: dim
+      integer(c_int) :: order
+      integer(c_int) :: numNodes
+      type(c_ptr), intent(out) :: api_localNodeCoord_
+      integer(c_size_t) :: api_localNodeCoord_n_
+      integer(c_int) :: numPrimaryNodes
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: elementType
+    character(len=:), allocatable, intent(out) :: elementName
+    integer(c_int) :: dim
+    integer(c_int) :: order
+    integer(c_int) :: numNodes
+    real(c_double), dimension(:), allocatable, intent(out) :: localNodeCoord
+    integer(c_int) :: numPrimaryNodes
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_localNodeCoord_
+    integer(c_size_t) :: api_localNodeCoord_n_
+    call C_API(elementType=int(elementType, c_int), &
+         api_elementName_=elementName, &
+         dim=dim, &
+         order=order, &
+         numNodes=numNodes, &
+         api_localNodeCoord_=api_localNodeCoord_, &
+         api_localNodeCoord_n_=api_localNodeCoord_n_, &
+         numPrimaryNodes=numPrimaryNodes, &
+         ierr_=ierr)
+    ! Post processing
+    localNodeCoord = ovectordouble_(api_localNodeCoord_, &
+      api_localNodeCoord_n_)
+  end subroutine gmshModelMeshGetElementProperties
+
+  !> Get the elements of type `elementType' classified on the entity of tag
+  !! `tag'. If `tag' < 0, get the elements for all entities. `elementTags' is a
+  !! vector containing 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 of the given type times the number N of nodes for
+  !! this type of element, that contains the node tags of all the elements of
+  !! the given type, concatenated: [e1n1, e1n2, ..., e1nN, e2n1, ...]. If
+  !! `numTasks' > 1, only compute and return the part of the data indexed by
+  !! `task'.
+  subroutine gmshModelMeshGetElementsByType(elementType, &
+                                            elementTags, &
+                                            nodeTags, &
+                                            tag, &
+                                            task, &
+                                            numTasks, &
+                                            ierr)
+    interface
+    subroutine C_API(elementType, &
+                     api_elementTags_, &
+                     api_elementTags_n_, &
+                     api_nodeTags_, &
+                     api_nodeTags_n_, &
+                     tag, &
+                     task, &
+                     numTasks, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetElementsByType")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: elementType
+      type(c_ptr), intent(out) :: api_elementTags_
+      integer(c_size_t), intent(out) :: api_elementTags_n_
+      type(c_ptr), intent(out) :: api_nodeTags_
+      integer(c_size_t), intent(out) :: api_nodeTags_n_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_size_t), value, intent(in) :: task
+      integer(c_size_t), value, intent(in) :: numTasks
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: elementType
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: elementTags
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: nodeTags
+    integer, intent(in), optional :: tag
+    integer, intent(in), optional :: task
+    integer, intent(in), optional :: numTasks
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_elementTags_
+    integer(c_size_t) :: api_elementTags_n_
+    type(c_ptr) :: api_nodeTags_
+    integer(c_size_t) :: api_nodeTags_n_
+    call C_API(elementType=int(elementType, c_int), &
+         api_elementTags_=api_elementTags_, &
+         api_elementTags_n_=api_elementTags_n_, &
+         api_nodeTags_=api_nodeTags_, &
+         api_nodeTags_n_=api_nodeTags_n_, &
+         tag=optval_c_int(-1, tag), &
+         task=optval_c_size_t(0, task), &
+         numTasks=optval_c_size_t(1, numTasks), &
+         ierr_=ierr)
+    ! Post processing
+    elementTags = ovectorsize_(api_elementTags_, &
+      api_elementTags_n_)
+    nodeTags = ovectorsize_(api_nodeTags_, &
+      api_nodeTags_n_)
+  end subroutine gmshModelMeshGetElementsByType
+
+  !> Get the maximum tag `maxTag' of an element in the mesh.
+  subroutine gmshModelMeshGetMaxElementTag(maxTag, &
+                                           ierr)
+    interface
+    subroutine C_API(maxTag, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetMaxElementTag")
+      use, intrinsic :: iso_c_binding
+      integer(c_size_t) :: maxTag
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_size_t) :: maxTag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(maxTag=maxTag, &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshGetMaxElementTag
+
+  !> Preallocate data before calling `getElementsByType' with `numTasks' > 1.
+  !! For C and C++ only.
+  subroutine gmshModelMeshPreallocateElementsByType(elementType, &
+                                                    elementTag, &
+                                                    nodeTag, &
+                                                    elementTags, &
+                                                    nodeTags, &
+                                                    tag, &
+                                                    ierr)
+    interface
+    subroutine C_API(elementType, &
+                     elementTag, &
+                     nodeTag, &
+                     api_elementTags_, &
+                     api_elementTags_n_, &
+                     api_nodeTags_, &
+                     api_nodeTags_n_, &
+                     tag, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshPreallocateElementsByType")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: elementType
+      integer(c_int), value, intent(in) :: elementTag
+      integer(c_int), value, intent(in) :: nodeTag
+      type(c_ptr), intent(out) :: api_elementTags_
+      integer(c_size_t), intent(out) :: api_elementTags_n_
+      type(c_ptr), intent(out) :: api_nodeTags_
+      integer(c_size_t), intent(out) :: api_nodeTags_n_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: elementType
+    logical, intent(in) :: elementTag
+    logical, intent(in) :: nodeTag
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: elementTags
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: nodeTags
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_elementTags_
+    integer(c_size_t) :: api_elementTags_n_
+    type(c_ptr) :: api_nodeTags_
+    integer(c_size_t) :: api_nodeTags_n_
+    call C_API(elementType=int(elementType, c_int), &
+         elementTag=merge(1_c_int, 0_c_int, elementTag), &
+         nodeTag=merge(1_c_int, 0_c_int, nodeTag), &
+         api_elementTags_=api_elementTags_, &
+         api_elementTags_n_=api_elementTags_n_, &
+         api_nodeTags_=api_nodeTags_, &
+         api_nodeTags_n_=api_nodeTags_n_, &
+         tag=optval_c_int(-1, tag), &
+         ierr_=ierr)
+    ! Post processing
+    elementTags = ovectorsize_(api_elementTags_, &
+      api_elementTags_n_)
+    nodeTags = ovectorsize_(api_nodeTags_, &
+      api_nodeTags_n_)
+  end subroutine gmshModelMeshPreallocateElementsByType
+
+  !> Get the quality `elementQualities' of the elements with tags `elementTags'.
+  !! `qualityType' is the requested quality measure: "minSJ" for the minimal
+  !! scaled jacobien, "minSICN" for the minimal signed inverted condition
+  !! number, "minSIGE" for the signed inverted gradient error, "gamma" for the
+  !! ratio of the inscribed to circumcribed sphere radius, "volume" for the
+  !! volume. If `numTasks' > 1, only compute and return the part of the data
+  !! indexed by `task'.
+  subroutine gmshModelMeshGetElementQualities(elementTags, &
+                                              elementsQuality, &
+                                              qualityName, &
+                                              task, &
+                                              numTasks, &
+                                              ierr)
+    interface
+    subroutine C_API(api_elementTags_, &
+                     api_elementTags_n_, &
+                     api_elementsQuality_, &
+                     api_elementsQuality_n_, &
+                     qualityName, &
+                     task, &
+                     numTasks, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetElementQualities")
+      use, intrinsic :: iso_c_binding
+      integer(c_size_t), dimension(*) :: api_elementTags_
+      integer(c_size_t), value, intent(in) :: api_elementTags_n_
+      type(c_ptr), intent(out) :: api_elementsQuality_
+      integer(c_size_t) :: api_elementsQuality_n_
+      character(len=1, kind=c_char), dimension(*), intent(in), optional :: qualityName
+      integer(c_size_t), value, intent(in) :: task
+      integer(c_size_t), value, intent(in) :: numTasks
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_size_t), dimension(:), intent(in) :: elementTags
+    real(c_double), dimension(:), allocatable, intent(out) :: elementsQuality
+    character(len=*), intent(in), optional :: qualityName
+    integer, intent(in), optional :: task
+    integer, intent(in), optional :: numTasks
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_elementsQuality_
+    integer(c_size_t) :: api_elementsQuality_n_
+    call C_API(api_elementTags_=elementTags, &
+         api_elementTags_n_=size_gmsh_size(elementTags), &
+         api_elementsQuality_=api_elementsQuality_, &
+         api_elementsQuality_n_=api_elementsQuality_n_, &
+         qualityName=istring_(optval_c_str("minSICN", qualityName)), &
+         task=optval_c_size_t(0, task), &
+         numTasks=optval_c_size_t(1, numTasks), &
+         ierr_=ierr)
+    ! Post processing
+    elementsQuality = ovectordouble_(api_elementsQuality_, &
+      api_elementsQuality_n_)
+  end subroutine gmshModelMeshGetElementQualities
+
+  !> 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,
+  !! ...].
+  subroutine gmshModelMeshAddElements(dim, &
+                                      tag, &
+                                      elementTypes, &
+                                      elementTags, &
+                                      elementTags_n, &
+                                      nodeTags, &
+                                      nodeTags_n, &
+                                      ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     api_elementTypes_, &
+                     api_elementTypes_n_, &
+                     api_elementTags_, &
+                     api_elementTags_n_, &
+                     api_elementTags_nn_, &
+                     api_nodeTags_, &
+                     api_nodeTags_n_, &
+                     api_nodeTags_nn_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshAddElements")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), dimension(*) :: api_elementTypes_
+      integer(c_size_t), value, intent(in) :: api_elementTypes_n_
+      type(c_ptr), intent(in) :: api_elementTags_
+      type(c_ptr), intent(in) :: api_elementTags_n_
+      integer(c_size_t), value, intent(in) :: api_elementTags_nn_
+      type(c_ptr), intent(in) :: api_nodeTags_
+      type(c_ptr), intent(in) :: api_nodeTags_n_
+      integer(c_size_t), value, intent(in) :: api_nodeTags_nn_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    integer(c_int), dimension(:), intent(in) :: elementTypes
+    integer(c_size_t), dimension(:), intent(in) :: elementTags
+    integer(c_size_t), dimension(:), intent(in) :: elementTags_n
+    integer(c_size_t), dimension(:), intent(in) :: nodeTags
+    integer(c_size_t), dimension(:), intent(in) :: nodeTags_n
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_elementTags_
+    type(c_ptr) :: api_elementTags_n_
+    integer(c_size_t) :: api_elementTags_nn_
+    type(c_ptr) :: api_nodeTags_
+    type(c_ptr) :: api_nodeTags_n_
+    integer(c_size_t) :: api_nodeTags_nn_
+    call ivectorvectorsize_(elementTags, &
+      elementTags_n, &
+      api_elementTags_, &
+      api_elementTags_n_, &
+      api_elementTags_nn_)
+    call ivectorvectorsize_(nodeTags, &
+      nodeTags_n, &
+      api_nodeTags_, &
+      api_nodeTags_n_, &
+      api_nodeTags_nn_)
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         api_elementTypes_=elementTypes, &
+         api_elementTypes_n_=size_gmsh_int(elementTypes), &
+         api_elementTags_=api_elementTags_, &
+         api_elementTags_n_=api_elementTags_n_, &
+         api_elementTags_nn_=api_elementTags_nn_, &
+         api_nodeTags_=api_nodeTags_, &
+         api_nodeTags_n_=api_nodeTags_n_, &
+         api_nodeTags_nn_=api_nodeTags_nn_, &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshAddElements
+
+  !> 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.
+  subroutine gmshModelMeshAddElementsByType(tag, &
+                                            elementType, &
+                                            elementTags, &
+                                            nodeTags, &
+                                            ierr)
+    interface
+    subroutine C_API(tag, &
+                     elementType, &
+                     api_elementTags_, &
+                     api_elementTags_n_, &
+                     api_nodeTags_, &
+                     api_nodeTags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshAddElementsByType")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: elementType
+      integer(c_size_t), dimension(*) :: api_elementTags_
+      integer(c_size_t), value, intent(in) :: api_elementTags_n_
+      integer(c_size_t), dimension(*) :: api_nodeTags_
+      integer(c_size_t), value, intent(in) :: api_nodeTags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    integer, intent(in) :: elementType
+    integer(c_size_t), dimension(:), intent(in) :: elementTags
+    integer(c_size_t), dimension(:), intent(in) :: nodeTags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(tag=int(tag, c_int), &
+         elementType=int(elementType, c_int), &
+         api_elementTags_=elementTags, &
+         api_elementTags_n_=size_gmsh_size(elementTags), &
+         api_nodeTags_=nodeTags, &
+         api_nodeTags_n_=size_gmsh_size(nodeTags), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshAddElementsByType
+
+  !> Get the numerical quadrature information for the given element type
+  !! `elementType' and integration rule `integrationType', where
+  !! `integrationType' concatenates the integration rule family name with the
+  !! desired order (e.g. "Gauss4" for a quadrature suited for integrating 4th
+  !! order polynomials). The "CompositeGauss" family uses tensor-product rules
+  !! based the 1D Gauss-Legendre rule; the "Gauss" family uses an economic
+  !! scheme when available (i.e. with a minimal number of points), and falls
+  !! back to "CompositeGauss" otherwise. Note that integration points for the
+  !! "Gauss" family can fall outside of the reference element for high-order
+  !! rules. `localCoord' contains the u, v, w coordinates of the G integration
+  !! points in the reference element: [g1u, g1v, g1w, ..., gGu, gGv, gGw].
+  !! `weights' contains the associated weights: [g1q, ..., gGq].
+  subroutine gmshModelMeshGetIntegrationPoints(elementType, &
+                                               integrationType, &
+                                               localCoord, &
+                                               weights, &
+                                               ierr)
+    interface
+    subroutine C_API(elementType, &
+                     integrationType, &
+                     api_localCoord_, &
+                     api_localCoord_n_, &
+                     api_weights_, &
+                     api_weights_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetIntegrationPoints")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: elementType
+      character(len=1, kind=c_char), dimension(*), intent(in) :: integrationType
+      type(c_ptr), intent(out) :: api_localCoord_
+      integer(c_size_t) :: api_localCoord_n_
+      type(c_ptr), intent(out) :: api_weights_
+      integer(c_size_t) :: api_weights_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: elementType
+    character(len=*), intent(in) :: integrationType
+    real(c_double), dimension(:), allocatable, intent(out) :: localCoord
+    real(c_double), dimension(:), allocatable, intent(out) :: weights
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_localCoord_
+    integer(c_size_t) :: api_localCoord_n_
+    type(c_ptr) :: api_weights_
+    integer(c_size_t) :: api_weights_n_
+    call C_API(elementType=int(elementType, c_int), &
+         integrationType=istring_(integrationType), &
+         api_localCoord_=api_localCoord_, &
+         api_localCoord_n_=api_localCoord_n_, &
+         api_weights_=api_weights_, &
+         api_weights_n_=api_weights_n_, &
+         ierr_=ierr)
+    ! Post processing
+    localCoord = ovectordouble_(api_localCoord_, &
+      api_localCoord_n_)
+    weights = ovectordouble_(api_weights_, &
+      api_weights_n_)
+  end subroutine gmshModelMeshGetIntegrationPoints
+
+  !> Get the Jacobians of all the elements of type `elementType' classified on
+  !! the entity of tag `tag', at the G evaluation points `localCoord' given as
+  !! concatenated triplets of coordinates in the reference element [g1u, g1v,
+  !! g1w, ..., gGu, gGv, gGw]. Data is returned by element, with elements in the
+  !! same order as in `getElements' and `getElementsByType'. `jacobians'
+  !! contains for each element the 9 entries of the 3x3 Jacobian matrix at each
+  !! evaluation point. The matrix is returned by column: [e1g1Jxu, e1g1Jyu,
+  !! e1g1Jzu, e1g1Jxv, ..., e1g1Jzw, e1g2Jxu, ..., e1gGJzw, e2g1Jxu, ...], with
+  !! Jxu=dx/du, Jyu=dy/du, etc. `determinants' contains for each element the
+  !! determinant of the Jacobian matrix at each evaluation point: [e1g1, e1g2,
+  !! ... e1gG, e2g1, ...]. `coord' contains for each element the x, y, z
+  !! coordinates of the evaluation points. If `tag' < 0, get the Jacobian data
+  !! for all entities. If `numTasks' > 1, only compute and return the part of
+  !! the data indexed by `task'.
+  subroutine gmshModelMeshGetJacobians(elementType, &
+                                       localCoord, &
+                                       jacobians, &
+                                       determinants, &
+                                       coord, &
+                                       tag, &
+                                       task, &
+                                       numTasks, &
+                                       ierr)
+    interface
+    subroutine C_API(elementType, &
+                     api_localCoord_, &
+                     api_localCoord_n_, &
+                     api_jacobians_, &
+                     api_jacobians_n_, &
+                     api_determinants_, &
+                     api_determinants_n_, &
+                     api_coord_, &
+                     api_coord_n_, &
+                     tag, &
+                     task, &
+                     numTasks, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetJacobians")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: elementType
+      real(c_double), dimension(*) :: api_localCoord_
+      integer(c_size_t), value, intent(in) :: api_localCoord_n_
+      type(c_ptr), intent(out) :: api_jacobians_
+      integer(c_size_t) :: api_jacobians_n_
+      type(c_ptr), intent(out) :: api_determinants_
+      integer(c_size_t) :: api_determinants_n_
+      type(c_ptr), intent(out) :: api_coord_
+      integer(c_size_t) :: api_coord_n_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_size_t), value, intent(in) :: task
+      integer(c_size_t), value, intent(in) :: numTasks
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: elementType
+    real(c_double), dimension(:), intent(in) :: localCoord
+    real(c_double), dimension(:), allocatable, intent(out) :: jacobians
+    real(c_double), dimension(:), allocatable, intent(out) :: determinants
+    real(c_double), dimension(:), allocatable, intent(out) :: coord
+    integer, intent(in), optional :: tag
+    integer, intent(in), optional :: task
+    integer, intent(in), optional :: numTasks
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_jacobians_
+    integer(c_size_t) :: api_jacobians_n_
+    type(c_ptr) :: api_determinants_
+    integer(c_size_t) :: api_determinants_n_
+    type(c_ptr) :: api_coord_
+    integer(c_size_t) :: api_coord_n_
+    call C_API(elementType=int(elementType, c_int), &
+         api_localCoord_=localCoord, &
+         api_localCoord_n_=size_gmsh_double(localCoord), &
+         api_jacobians_=api_jacobians_, &
+         api_jacobians_n_=api_jacobians_n_, &
+         api_determinants_=api_determinants_, &
+         api_determinants_n_=api_determinants_n_, &
+         api_coord_=api_coord_, &
+         api_coord_n_=api_coord_n_, &
+         tag=optval_c_int(-1, tag), &
+         task=optval_c_size_t(0, task), &
+         numTasks=optval_c_size_t(1, numTasks), &
+         ierr_=ierr)
+    ! Post processing
+    jacobians = ovectordouble_(api_jacobians_, &
+      api_jacobians_n_)
+    determinants = ovectordouble_(api_determinants_, &
+      api_determinants_n_)
+    coord = ovectordouble_(api_coord_, &
+      api_coord_n_)
+  end subroutine gmshModelMeshGetJacobians
+
+  !> Preallocate data before calling `getJacobians' with `numTasks' > 1. For C
+  !! and C++ only.
+  subroutine gmshModelMeshPreallocateJacobians(elementType, &
+                                               numEvaluationPoints, &
+                                               allocateJacobians, &
+                                               allocateDeterminants, &
+                                               allocateCoord, &
+                                               jacobians, &
+                                               determinants, &
+                                               coord, &
+                                               tag, &
+                                               ierr)
+    interface
+    subroutine C_API(elementType, &
+                     numEvaluationPoints, &
+                     allocateJacobians, &
+                     allocateDeterminants, &
+                     allocateCoord, &
+                     api_jacobians_, &
+                     api_jacobians_n_, &
+                     api_determinants_, &
+                     api_determinants_n_, &
+                     api_coord_, &
+                     api_coord_n_, &
+                     tag, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshPreallocateJacobians")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: elementType
+      integer(c_int), value, intent(in) :: numEvaluationPoints
+      integer(c_int), value, intent(in) :: allocateJacobians
+      integer(c_int), value, intent(in) :: allocateDeterminants
+      integer(c_int), value, intent(in) :: allocateCoord
+      type(c_ptr), intent(out) :: api_jacobians_
+      integer(c_size_t) :: api_jacobians_n_
+      type(c_ptr), intent(out) :: api_determinants_
+      integer(c_size_t) :: api_determinants_n_
+      type(c_ptr), intent(out) :: api_coord_
+      integer(c_size_t) :: api_coord_n_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: elementType
+    integer, intent(in) :: numEvaluationPoints
+    logical, intent(in) :: allocateJacobians
+    logical, intent(in) :: allocateDeterminants
+    logical, intent(in) :: allocateCoord
+    real(c_double), dimension(:), allocatable, intent(out) :: jacobians
+    real(c_double), dimension(:), allocatable, intent(out) :: determinants
+    real(c_double), dimension(:), allocatable, intent(out) :: coord
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_jacobians_
+    integer(c_size_t) :: api_jacobians_n_
+    type(c_ptr) :: api_determinants_
+    integer(c_size_t) :: api_determinants_n_
+    type(c_ptr) :: api_coord_
+    integer(c_size_t) :: api_coord_n_
+    call C_API(elementType=int(elementType, c_int), &
+         numEvaluationPoints=int(numEvaluationPoints, c_int), &
+         allocateJacobians=merge(1_c_int, 0_c_int, allocateJacobians), &
+         allocateDeterminants=merge(1_c_int, 0_c_int, allocateDeterminants), &
+         allocateCoord=merge(1_c_int, 0_c_int, allocateCoord), &
+         api_jacobians_=api_jacobians_, &
+         api_jacobians_n_=api_jacobians_n_, &
+         api_determinants_=api_determinants_, &
+         api_determinants_n_=api_determinants_n_, &
+         api_coord_=api_coord_, &
+         api_coord_n_=api_coord_n_, &
+         tag=optval_c_int(-1, tag), &
+         ierr_=ierr)
+    ! Post processing
+    jacobians = ovectordouble_(api_jacobians_, &
+      api_jacobians_n_)
+    determinants = ovectordouble_(api_determinants_, &
+      api_determinants_n_)
+    coord = ovectordouble_(api_coord_, &
+      api_coord_n_)
+  end subroutine gmshModelMeshPreallocateJacobians
+
+  !> Get the Jacobian for a single element `elementTag', at the G evaluation
+  !! points `localCoord' given as concatenated triplets of coordinates in the
+  !! reference element [g1u, g1v, g1w, ..., gGu, gGv, gGw]. `jacobians' contains
+  !! the 9 entries of the 3x3 Jacobian matrix at each evaluation point. The
+  !! matrix is returned by column: [e1g1Jxu, e1g1Jyu, e1g1Jzu, e1g1Jxv, ...,
+  !! e1g1Jzw, e1g2Jxu, ..., e1gGJzw, e2g1Jxu, ...], with Jxu=dx/du, Jyu=dy/du,
+  !! etc. `determinants' contains the determinant of the Jacobian matrix at each
+  !! evaluation point. `coord' contains the x, y, z coordinates of the
+  !! evaluation points. This function relies on an internal cache (a vector in
+  !! case of dense element numbering, a map otherwise); for large meshes
+  !! accessing Jacobians in bulk is often preferable.
+  subroutine gmshModelMeshGetJacobian(elementTag, &
+                                      localCoord, &
+                                      jacobians, &
+                                      determinants, &
+                                      coord, &
+                                      ierr)
+    interface
+    subroutine C_API(elementTag, &
+                     api_localCoord_, &
+                     api_localCoord_n_, &
+                     api_jacobians_, &
+                     api_jacobians_n_, &
+                     api_determinants_, &
+                     api_determinants_n_, &
+                     api_coord_, &
+                     api_coord_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetJacobian")
+      use, intrinsic :: iso_c_binding
+      integer(c_size_t), value, intent(in) :: elementTag
+      real(c_double), dimension(*) :: api_localCoord_
+      integer(c_size_t), value, intent(in) :: api_localCoord_n_
+      type(c_ptr), intent(out) :: api_jacobians_
+      integer(c_size_t) :: api_jacobians_n_
+      type(c_ptr), intent(out) :: api_determinants_
+      integer(c_size_t) :: api_determinants_n_
+      type(c_ptr), intent(out) :: api_coord_
+      integer(c_size_t) :: api_coord_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: elementTag
+    real(c_double), dimension(:), intent(in) :: localCoord
+    real(c_double), dimension(:), allocatable, intent(out) :: jacobians
+    real(c_double), dimension(:), allocatable, intent(out) :: determinants
+    real(c_double), dimension(:), allocatable, intent(out) :: coord
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_jacobians_
+    integer(c_size_t) :: api_jacobians_n_
+    type(c_ptr) :: api_determinants_
+    integer(c_size_t) :: api_determinants_n_
+    type(c_ptr) :: api_coord_
+    integer(c_size_t) :: api_coord_n_
+    call C_API(elementTag=int(elementTag, c_size_t), &
+         api_localCoord_=localCoord, &
+         api_localCoord_n_=size_gmsh_double(localCoord), &
+         api_jacobians_=api_jacobians_, &
+         api_jacobians_n_=api_jacobians_n_, &
+         api_determinants_=api_determinants_, &
+         api_determinants_n_=api_determinants_n_, &
+         api_coord_=api_coord_, &
+         api_coord_n_=api_coord_n_, &
+         ierr_=ierr)
+    ! Post processing
+    jacobians = ovectordouble_(api_jacobians_, &
+      api_jacobians_n_)
+    determinants = ovectordouble_(api_determinants_, &
+      api_determinants_n_)
+    coord = ovectordouble_(api_coord_, &
+      api_coord_n_)
+  end subroutine gmshModelMeshGetJacobian
+
+  !> Get the basis functions of the element of type `elementType' at the
+  !! evaluation points `localCoord' (given as concatenated triplets of
+  !! coordinates in the reference element [g1u, g1v, g1w, ..., gGu, gGv, gGw]),
+  !! for the function space `functionSpaceType'. Currently supported function
+  !! spaces include "Lagrange" and "GradLagrange" for isoparametric Lagrange
+  !! basis functions and their gradient in the u, v, w coordinates of the
+  !! reference element; "LagrangeN" and "GradLagrangeN", with N = 1, 2, ..., for
+  !! N-th order Lagrange basis functions; "H1LegendreN" and "GradH1LegendreN",
+  !! with N = 1, 2, ..., for N-th order hierarchical H1 Legendre functions;
+  !! "HcurlLegendreN" and "CurlHcurlLegendreN", with N = 1, 2, ..., for N-th
+  !! order curl-conforming basis functions. `numComponents' returns the number C
+  !! of components of a basis function (e.g. 1 for scalar functions and 3 for
+  !! vector functions). `basisFunctions' returns the value of the N basis
+  !! functions at the evaluation points, i.e. [g1f1, g1f2, ..., g1fN, g2f1, ...]
+  !! when C == 1 or [g1f1u, g1f1v, g1f1w, g1f2u, ..., g1fNw, g2f1u, ...] when C
+  !! == 3. For basis functions that depend on the orientation of the elements,
+  !! all values for the first orientation are returned first, followed by values
+  !! for the second, etc. `numOrientations' returns the overall number of
+  !! orientations. If `wantedOrientations' is not empty, only return the values
+  !! for the desired orientation indices.
+  subroutine gmshModelMeshGetBasisFunctions(elementType, &
+                                            localCoord, &
+                                            functionSpaceType, &
+                                            numComponents, &
+                                            basisFunctions, &
+                                            numOrientations, &
+                                            wantedOrientations, &
+                                            ierr)
+    interface
+    subroutine C_API(elementType, &
+                     api_localCoord_, &
+                     api_localCoord_n_, &
+                     functionSpaceType, &
+                     numComponents, &
+                     api_basisFunctions_, &
+                     api_basisFunctions_n_, &
+                     numOrientations, &
+                     api_wantedOrientations_, &
+                     api_wantedOrientations_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetBasisFunctions")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: elementType
+      real(c_double), dimension(*) :: api_localCoord_
+      integer(c_size_t), value, intent(in) :: api_localCoord_n_
+      character(len=1, kind=c_char), dimension(*), intent(in) :: functionSpaceType
+      integer(c_int) :: numComponents
+      type(c_ptr), intent(out) :: api_basisFunctions_
+      integer(c_size_t) :: api_basisFunctions_n_
+      integer(c_int) :: numOrientations
+      integer(c_int), dimension(*), optional :: api_wantedOrientations_
+      integer(c_size_t), value, intent(in) :: api_wantedOrientations_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: elementType
+    real(c_double), dimension(:), intent(in) :: localCoord
+    character(len=*), intent(in) :: functionSpaceType
+    integer(c_int) :: numComponents
+    real(c_double), dimension(:), allocatable, intent(out) :: basisFunctions
+    integer(c_int) :: numOrientations
+    integer(c_int), dimension(:), intent(in), optional :: wantedOrientations
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_basisFunctions_
+    integer(c_size_t) :: api_basisFunctions_n_
+    call C_API(elementType=int(elementType, c_int), &
+         api_localCoord_=localCoord, &
+         api_localCoord_n_=size_gmsh_double(localCoord), &
+         functionSpaceType=istring_(functionSpaceType), &
+         numComponents=numComponents, &
+         api_basisFunctions_=api_basisFunctions_, &
+         api_basisFunctions_n_=api_basisFunctions_n_, &
+         numOrientations=numOrientations, &
+         api_wantedOrientations_=wantedOrientations, &
+         api_wantedOrientations_n_=size_gmsh_int(wantedOrientations), &
+         ierr_=ierr)
+    ! Post processing
+    basisFunctions = ovectordouble_(api_basisFunctions_, &
+      api_basisFunctions_n_)
+  end subroutine gmshModelMeshGetBasisFunctions
+
+  !> Get the orientation index of the elements of type `elementType' in the
+  !! entity of tag `tag'. The arguments have the same meaning as in
+  !! `getBasisFunctions'. `basisFunctionsOrientation' is a vector giving for
+  !! each element the orientation index in the values returned by
+  !! `getBasisFunctions'. For Lagrange basis functions the call is superfluous
+  !! as it will return a vector of zeros.
+  subroutine gmshModelMeshGetBasisFunctionsOrientation(elementType, &
+                                                       functionSpaceType, &
+                                                       basisFunctionsOrientation, &
+                                                       tag, &
+                                                       task, &
+                                                       numTasks, &
+                                                       ierr)
+    interface
+    subroutine C_API(elementType, &
+                     functionSpaceType, &
+                     api_basisFunctionsOrientation_, &
+                     api_basisFunctionsOrientation_n_, &
+                     tag, &
+                     task, &
+                     numTasks, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetBasisFunctionsOrientation")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: elementType
+      character(len=1, kind=c_char), dimension(*), intent(in) :: functionSpaceType
+      type(c_ptr), intent(out) :: api_basisFunctionsOrientation_
+      integer(c_size_t), intent(out) :: api_basisFunctionsOrientation_n_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_size_t), value, intent(in) :: task
+      integer(c_size_t), value, intent(in) :: numTasks
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: elementType
+    character(len=*), intent(in) :: functionSpaceType
+    integer(c_int), dimension(:), allocatable, intent(out) :: basisFunctionsOrientation
+    integer, intent(in), optional :: tag
+    integer, intent(in), optional :: task
+    integer, intent(in), optional :: numTasks
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_basisFunctionsOrientation_
+    integer(c_size_t) :: api_basisFunctionsOrientation_n_
+    call C_API(elementType=int(elementType, c_int), &
+         functionSpaceType=istring_(functionSpaceType), &
+         api_basisFunctionsOrientation_=api_basisFunctionsOrientation_, &
+         api_basisFunctionsOrientation_n_=api_basisFunctionsOrientation_n_, &
+         tag=optval_c_int(-1, tag), &
+         task=optval_c_size_t(0, task), &
+         numTasks=optval_c_size_t(1, numTasks), &
+         ierr_=ierr)
+    ! Post processing
+    basisFunctionsOrientation = ovectorint_(api_basisFunctionsOrientation_, &
+      api_basisFunctionsOrientation_n_)
+  end subroutine gmshModelMeshGetBasisFunctionsOrientation
+
+  !> Get the orientation of a single element `elementTag'.
+  subroutine gmshModelMeshGetBasisFunctionsOrientationForElement(elementTag, &
+                                                                 functionSpaceType, &
+                                                                 basisFunctionsOrientation, &
+                                                                 ierr)
+    interface
+    subroutine C_API(elementTag, &
+                     functionSpaceType, &
+                     basisFunctionsOrientation, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetBasisFunctionsOrientationForElement")
+      use, intrinsic :: iso_c_binding
+      integer(c_size_t), value, intent(in) :: elementTag
+      character(len=1, kind=c_char), dimension(*), intent(in) :: functionSpaceType
+      integer(c_int) :: basisFunctionsOrientation
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: elementTag
+    character(len=*), intent(in) :: functionSpaceType
+    integer(c_int) :: basisFunctionsOrientation
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(elementTag=int(elementTag, c_size_t), &
+         functionSpaceType=istring_(functionSpaceType), &
+         basisFunctionsOrientation=basisFunctionsOrientation, &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshGetBasisFunctionsOrientationForElement
+
+  !> Get the number of possible orientations for elements of type `elementType'
+  !! and function space named `functionSpaceType'.
+  function gmshModelMeshGetNumberOfOrientations(elementType, &
+                                                functionSpaceType, &
+                                                ierr)
+    interface
+    function C_API(elementType, &
+                   functionSpaceType, &
+                   ierr_) &
+      bind(C, name="gmshModelMeshGetNumberOfOrientations")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), value, intent(in) :: elementType
+      character(len=1, kind=c_char), dimension(*), intent(in) :: functionSpaceType
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelMeshGetNumberOfOrientations
+    integer, intent(in) :: elementType
+    character(len=*), intent(in) :: functionSpaceType
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelMeshGetNumberOfOrientations = C_API(elementType=int(elementType, c_int), &
+                                           functionSpaceType=istring_(functionSpaceType), &
+                                           ierr_=ierr)
+    ! Post processing
+  end function gmshModelMeshGetNumberOfOrientations
+
+  !> Preallocate data before calling `getBasisFunctionsOrientation' with
+  !! `numTasks' > 1. For C and C++ only.
+  subroutine gmshModelMeshPreallocateBasisFunctionsOrientation(elementType, &
+                                                               basisFunctionsOrientation, &
+                                                               tag, &
+                                                               ierr)
+    interface
+    subroutine C_API(elementType, &
+                     api_basisFunctionsOrientation_, &
+                     api_basisFunctionsOrientation_n_, &
+                     tag, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshPreallocateBasisFunctionsOrientation")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: elementType
+      type(c_ptr), intent(out) :: api_basisFunctionsOrientation_
+      integer(c_size_t), intent(out) :: api_basisFunctionsOrientation_n_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: elementType
+    integer(c_int), dimension(:), allocatable, intent(out) :: basisFunctionsOrientation
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_basisFunctionsOrientation_
+    integer(c_size_t) :: api_basisFunctionsOrientation_n_
+    call C_API(elementType=int(elementType, c_int), &
+         api_basisFunctionsOrientation_=api_basisFunctionsOrientation_, &
+         api_basisFunctionsOrientation_n_=api_basisFunctionsOrientation_n_, &
+         tag=optval_c_int(-1, tag), &
+         ierr_=ierr)
+    ! Post processing
+    basisFunctionsOrientation = ovectorint_(api_basisFunctionsOrientation_, &
+      api_basisFunctionsOrientation_n_)
+  end subroutine gmshModelMeshPreallocateBasisFunctionsOrientation
+
+  !> Get the global unique mesh edge identifiers `edgeTags' and orientations
+  !! `edgeOrientation' for an input list of node tag pairs defining these edges,
+  !! concatenated in the vector `nodeTags'. Mesh edges are created e.g. by
+  !! `createEdges()', `getKeys()' or `addEdges()'. The reference positive
+  !! orientation is n1 < n2, where n1 and n2 are the tags of the two edge nodes,
+  !! which corresponds to the local orientation of edge-based basis functions as
+  !! well.
+  subroutine gmshModelMeshGetEdges(nodeTags, &
+                                   edgeTags, &
+                                   edgeOrientations, &
+                                   ierr)
+    interface
+    subroutine C_API(api_nodeTags_, &
+                     api_nodeTags_n_, &
+                     api_edgeTags_, &
+                     api_edgeTags_n_, &
+                     api_edgeOrientations_, &
+                     api_edgeOrientations_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetEdges")
+      use, intrinsic :: iso_c_binding
+      integer(c_size_t), dimension(*) :: api_nodeTags_
+      integer(c_size_t), value, intent(in) :: api_nodeTags_n_
+      type(c_ptr), intent(out) :: api_edgeTags_
+      integer(c_size_t), intent(out) :: api_edgeTags_n_
+      type(c_ptr), intent(out) :: api_edgeOrientations_
+      integer(c_size_t), intent(out) :: api_edgeOrientations_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_size_t), dimension(:), intent(in) :: nodeTags
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: edgeTags
+    integer(c_int), dimension(:), allocatable, intent(out) :: edgeOrientations
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_edgeTags_
+    integer(c_size_t) :: api_edgeTags_n_
+    type(c_ptr) :: api_edgeOrientations_
+    integer(c_size_t) :: api_edgeOrientations_n_
+    call C_API(api_nodeTags_=nodeTags, &
+         api_nodeTags_n_=size_gmsh_size(nodeTags), &
+         api_edgeTags_=api_edgeTags_, &
+         api_edgeTags_n_=api_edgeTags_n_, &
+         api_edgeOrientations_=api_edgeOrientations_, &
+         api_edgeOrientations_n_=api_edgeOrientations_n_, &
+         ierr_=ierr)
+    ! Post processing
+    edgeTags = ovectorsize_(api_edgeTags_, &
+      api_edgeTags_n_)
+    edgeOrientations = ovectorint_(api_edgeOrientations_, &
+      api_edgeOrientations_n_)
+  end subroutine gmshModelMeshGetEdges
+
+  !> Get the global unique mesh face identifiers `faceTags' and orientations
+  !! `faceOrientations' for an input list of node tag triplets (if `faceType' ==
+  !! 3) or quadruplets (if `faceType' == 4) defining these faces, concatenated
+  !! in the vector `nodeTags'. Mesh faces are created e.g. by `createFaces()',
+  !! `getKeys()' or `addFaces()'.
+  subroutine gmshModelMeshGetFaces(faceType, &
+                                   nodeTags, &
+                                   faceTags, &
+                                   faceOrientations, &
+                                   ierr)
+    interface
+    subroutine C_API(faceType, &
+                     api_nodeTags_, &
+                     api_nodeTags_n_, &
+                     api_faceTags_, &
+                     api_faceTags_n_, &
+                     api_faceOrientations_, &
+                     api_faceOrientations_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetFaces")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: faceType
+      integer(c_size_t), dimension(*) :: api_nodeTags_
+      integer(c_size_t), value, intent(in) :: api_nodeTags_n_
+      type(c_ptr), intent(out) :: api_faceTags_
+      integer(c_size_t), intent(out) :: api_faceTags_n_
+      type(c_ptr), intent(out) :: api_faceOrientations_
+      integer(c_size_t), intent(out) :: api_faceOrientations_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: faceType
+    integer(c_size_t), dimension(:), intent(in) :: nodeTags
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: faceTags
+    integer(c_int), dimension(:), allocatable, intent(out) :: faceOrientations
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_faceTags_
+    integer(c_size_t) :: api_faceTags_n_
+    type(c_ptr) :: api_faceOrientations_
+    integer(c_size_t) :: api_faceOrientations_n_
+    call C_API(faceType=int(faceType, c_int), &
+         api_nodeTags_=nodeTags, &
+         api_nodeTags_n_=size_gmsh_size(nodeTags), &
+         api_faceTags_=api_faceTags_, &
+         api_faceTags_n_=api_faceTags_n_, &
+         api_faceOrientations_=api_faceOrientations_, &
+         api_faceOrientations_n_=api_faceOrientations_n_, &
+         ierr_=ierr)
+    ! Post processing
+    faceTags = ovectorsize_(api_faceTags_, &
+      api_faceTags_n_)
+    faceOrientations = ovectorint_(api_faceOrientations_, &
+      api_faceOrientations_n_)
+  end subroutine gmshModelMeshGetFaces
+
+  !> Create unique mesh edges for the entities `dimTags'.
+  subroutine gmshModelMeshCreateEdges(dimTags, &
+                                      ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshCreateEdges")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*), optional :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in), optional :: dimTags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshCreateEdges
+
+  !> Create unique mesh faces for the entities `dimTags'.
+  subroutine gmshModelMeshCreateFaces(dimTags, &
+                                      ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshCreateFaces")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*), optional :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in), optional :: dimTags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshCreateFaces
+
+  !> Get the global unique identifiers `edgeTags' and the nodes `edgeNodes' of
+  !! the edges in the mesh. Mesh edges are created e.g. by `createEdges()',
+  !! `getKeys()' or addEdges().
+  subroutine gmshModelMeshGetAllEdges(edgeTags, &
+                                      edgeNodes, &
+                                      ierr)
+    interface
+    subroutine C_API(api_edgeTags_, &
+                     api_edgeTags_n_, &
+                     api_edgeNodes_, &
+                     api_edgeNodes_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetAllEdges")
+      use, intrinsic :: iso_c_binding
+      type(c_ptr), intent(out) :: api_edgeTags_
+      integer(c_size_t), intent(out) :: api_edgeTags_n_
+      type(c_ptr), intent(out) :: api_edgeNodes_
+      integer(c_size_t), intent(out) :: api_edgeNodes_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: edgeTags
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: edgeNodes
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_edgeTags_
+    integer(c_size_t) :: api_edgeTags_n_
+    type(c_ptr) :: api_edgeNodes_
+    integer(c_size_t) :: api_edgeNodes_n_
+    call C_API(api_edgeTags_=api_edgeTags_, &
+         api_edgeTags_n_=api_edgeTags_n_, &
+         api_edgeNodes_=api_edgeNodes_, &
+         api_edgeNodes_n_=api_edgeNodes_n_, &
+         ierr_=ierr)
+    ! Post processing
+    edgeTags = ovectorsize_(api_edgeTags_, &
+      api_edgeTags_n_)
+    edgeNodes = ovectorsize_(api_edgeNodes_, &
+      api_edgeNodes_n_)
+  end subroutine gmshModelMeshGetAllEdges
+
+  !> Get the global unique identifiers `faceTags' and the nodes `faceNodes' of
+  !! the faces of type `faceType' in the mesh. Mesh faces are created e.g. by
+  !! `createFaces()', `getKeys()' or addFaces().
+  subroutine gmshModelMeshGetAllFaces(faceType, &
+                                      faceTags, &
+                                      faceNodes, &
+                                      ierr)
+    interface
+    subroutine C_API(faceType, &
+                     api_faceTags_, &
+                     api_faceTags_n_, &
+                     api_faceNodes_, &
+                     api_faceNodes_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetAllFaces")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: faceType
+      type(c_ptr), intent(out) :: api_faceTags_
+      integer(c_size_t), intent(out) :: api_faceTags_n_
+      type(c_ptr), intent(out) :: api_faceNodes_
+      integer(c_size_t), intent(out) :: api_faceNodes_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: faceType
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: faceTags
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: faceNodes
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_faceTags_
+    integer(c_size_t) :: api_faceTags_n_
+    type(c_ptr) :: api_faceNodes_
+    integer(c_size_t) :: api_faceNodes_n_
+    call C_API(faceType=int(faceType, c_int), &
+         api_faceTags_=api_faceTags_, &
+         api_faceTags_n_=api_faceTags_n_, &
+         api_faceNodes_=api_faceNodes_, &
+         api_faceNodes_n_=api_faceNodes_n_, &
+         ierr_=ierr)
+    ! Post processing
+    faceTags = ovectorsize_(api_faceTags_, &
+      api_faceTags_n_)
+    faceNodes = ovectorsize_(api_faceNodes_, &
+      api_faceNodes_n_)
+  end subroutine gmshModelMeshGetAllFaces
+
+  !> Add mesh edges defined by their global unique identifiers `edgeTags' and
+  !! their nodes `edgeNodes'.
+  subroutine gmshModelMeshAddEdges(edgeTags, &
+                                   edgeNodes, &
+                                   ierr)
+    interface
+    subroutine C_API(api_edgeTags_, &
+                     api_edgeTags_n_, &
+                     api_edgeNodes_, &
+                     api_edgeNodes_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshAddEdges")
+      use, intrinsic :: iso_c_binding
+      integer(c_size_t), dimension(*) :: api_edgeTags_
+      integer(c_size_t), value, intent(in) :: api_edgeTags_n_
+      integer(c_size_t), dimension(*) :: api_edgeNodes_
+      integer(c_size_t), value, intent(in) :: api_edgeNodes_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_size_t), dimension(:), intent(in) :: edgeTags
+    integer(c_size_t), dimension(:), intent(in) :: edgeNodes
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_edgeTags_=edgeTags, &
+         api_edgeTags_n_=size_gmsh_size(edgeTags), &
+         api_edgeNodes_=edgeNodes, &
+         api_edgeNodes_n_=size_gmsh_size(edgeNodes), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshAddEdges
+
+  !> Add mesh faces of type `faceType' defined by their global unique
+  !! identifiers `faceTags' and their nodes `faceNodes'.
+  subroutine gmshModelMeshAddFaces(faceType, &
+                                   faceTags, &
+                                   faceNodes, &
+                                   ierr)
+    interface
+    subroutine C_API(faceType, &
+                     api_faceTags_, &
+                     api_faceTags_n_, &
+                     api_faceNodes_, &
+                     api_faceNodes_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshAddFaces")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: faceType
+      integer(c_size_t), dimension(*) :: api_faceTags_
+      integer(c_size_t), value, intent(in) :: api_faceTags_n_
+      integer(c_size_t), dimension(*) :: api_faceNodes_
+      integer(c_size_t), value, intent(in) :: api_faceNodes_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: faceType
+    integer(c_size_t), dimension(:), intent(in) :: faceTags
+    integer(c_size_t), dimension(:), intent(in) :: faceNodes
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(faceType=int(faceType, c_int), &
+         api_faceTags_=faceTags, &
+         api_faceTags_n_=size_gmsh_size(faceTags), &
+         api_faceNodes_=faceNodes, &
+         api_faceNodes_n_=size_gmsh_size(faceNodes), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshAddFaces
+
+  !> Generate the pair of keys for the elements of type `elementType' in the
+  !! entity of tag `tag', for the `functionSpaceType' function space. Each pair
+  !! (`typeKey', `entityKey') uniquely identifies a basis function in the
+  !! function space. If `returnCoord' is set, the `coord' vector contains the x,
+  !! y, z coordinates locating basis functions for sorting purposes. Warning:
+  !! this is an experimental feature and will probably change in a future
+  !! release.
+  subroutine gmshModelMeshGetKeys(elementType, &
+                                  functionSpaceType, &
+                                  typeKeys, &
+                                  entityKeys, &
+                                  coord, &
+                                  tag, &
+                                  returnCoord, &
+                                  ierr)
+    interface
+    subroutine C_API(elementType, &
+                     functionSpaceType, &
+                     api_typeKeys_, &
+                     api_typeKeys_n_, &
+                     api_entityKeys_, &
+                     api_entityKeys_n_, &
+                     api_coord_, &
+                     api_coord_n_, &
+                     tag, &
+                     returnCoord, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetKeys")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: elementType
+      character(len=1, kind=c_char), dimension(*), intent(in) :: functionSpaceType
+      type(c_ptr), intent(out) :: api_typeKeys_
+      integer(c_size_t), intent(out) :: api_typeKeys_n_
+      type(c_ptr), intent(out) :: api_entityKeys_
+      integer(c_size_t), intent(out) :: api_entityKeys_n_
+      type(c_ptr), intent(out) :: api_coord_
+      integer(c_size_t) :: api_coord_n_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: returnCoord
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: elementType
+    character(len=*), intent(in) :: functionSpaceType
+    integer(c_int), dimension(:), allocatable, intent(out) :: typeKeys
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: entityKeys
+    real(c_double), dimension(:), allocatable, intent(out) :: coord
+    integer, intent(in), optional :: tag
+    logical, intent(in), optional :: returnCoord
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_typeKeys_
+    integer(c_size_t) :: api_typeKeys_n_
+    type(c_ptr) :: api_entityKeys_
+    integer(c_size_t) :: api_entityKeys_n_
+    type(c_ptr) :: api_coord_
+    integer(c_size_t) :: api_coord_n_
+    call C_API(elementType=int(elementType, c_int), &
+         functionSpaceType=istring_(functionSpaceType), &
+         api_typeKeys_=api_typeKeys_, &
+         api_typeKeys_n_=api_typeKeys_n_, &
+         api_entityKeys_=api_entityKeys_, &
+         api_entityKeys_n_=api_entityKeys_n_, &
+         api_coord_=api_coord_, &
+         api_coord_n_=api_coord_n_, &
+         tag=optval_c_int(-1, tag), &
+         returnCoord=optval_c_bool(.true., returnCoord), &
+         ierr_=ierr)
+    ! Post processing
+    typeKeys = ovectorint_(api_typeKeys_, &
+      api_typeKeys_n_)
+    entityKeys = ovectorsize_(api_entityKeys_, &
+      api_entityKeys_n_)
+    coord = ovectordouble_(api_coord_, &
+      api_coord_n_)
+  end subroutine gmshModelMeshGetKeys
+
+  !> Get the pair of keys for a single element `elementTag'.
+  subroutine gmshModelMeshGetKeysForElement(elementTag, &
+                                            functionSpaceType, &
+                                            typeKeys, &
+                                            entityKeys, &
+                                            coord, &
+                                            returnCoord, &
+                                            ierr)
+    interface
+    subroutine C_API(elementTag, &
+                     functionSpaceType, &
+                     api_typeKeys_, &
+                     api_typeKeys_n_, &
+                     api_entityKeys_, &
+                     api_entityKeys_n_, &
+                     api_coord_, &
+                     api_coord_n_, &
+                     returnCoord, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetKeysForElement")
+      use, intrinsic :: iso_c_binding
+      integer(c_size_t), value, intent(in) :: elementTag
+      character(len=1, kind=c_char), dimension(*), intent(in) :: functionSpaceType
+      type(c_ptr), intent(out) :: api_typeKeys_
+      integer(c_size_t), intent(out) :: api_typeKeys_n_
+      type(c_ptr), intent(out) :: api_entityKeys_
+      integer(c_size_t), intent(out) :: api_entityKeys_n_
+      type(c_ptr), intent(out) :: api_coord_
+      integer(c_size_t) :: api_coord_n_
+      integer(c_int), value, intent(in) :: returnCoord
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: elementTag
+    character(len=*), intent(in) :: functionSpaceType
+    integer(c_int), dimension(:), allocatable, intent(out) :: typeKeys
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: entityKeys
+    real(c_double), dimension(:), allocatable, intent(out) :: coord
+    logical, intent(in), optional :: returnCoord
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_typeKeys_
+    integer(c_size_t) :: api_typeKeys_n_
+    type(c_ptr) :: api_entityKeys_
+    integer(c_size_t) :: api_entityKeys_n_
+    type(c_ptr) :: api_coord_
+    integer(c_size_t) :: api_coord_n_
+    call C_API(elementTag=int(elementTag, c_size_t), &
+         functionSpaceType=istring_(functionSpaceType), &
+         api_typeKeys_=api_typeKeys_, &
+         api_typeKeys_n_=api_typeKeys_n_, &
+         api_entityKeys_=api_entityKeys_, &
+         api_entityKeys_n_=api_entityKeys_n_, &
+         api_coord_=api_coord_, &
+         api_coord_n_=api_coord_n_, &
+         returnCoord=optval_c_bool(.true., returnCoord), &
+         ierr_=ierr)
+    ! Post processing
+    typeKeys = ovectorint_(api_typeKeys_, &
+      api_typeKeys_n_)
+    entityKeys = ovectorsize_(api_entityKeys_, &
+      api_entityKeys_n_)
+    coord = ovectordouble_(api_coord_, &
+      api_coord_n_)
+  end subroutine gmshModelMeshGetKeysForElement
+
+  !> Get the number of keys by elements of type `elementType' for function space
+  !! named `functionSpaceType'.
+  function gmshModelMeshGetNumberOfKeys(elementType, &
+                                        functionSpaceType, &
+                                        ierr)
+    interface
+    function C_API(elementType, &
+                   functionSpaceType, &
+                   ierr_) &
+      bind(C, name="gmshModelMeshGetNumberOfKeys")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), value, intent(in) :: elementType
+      character(len=1, kind=c_char), dimension(*), intent(in) :: functionSpaceType
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelMeshGetNumberOfKeys
+    integer, intent(in) :: elementType
+    character(len=*), intent(in) :: functionSpaceType
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelMeshGetNumberOfKeys = C_API(elementType=int(elementType, c_int), &
+                                   functionSpaceType=istring_(functionSpaceType), &
+                                   ierr_=ierr)
+    ! Post processing
+  end function gmshModelMeshGetNumberOfKeys
+
+  !> Get information about the pair of `keys'. `infoKeys' returns information
+  !! about the functions associated with the pairs (`typeKeys', `entityKey').
+  !! `infoKeys[0].first' describes the type of function (0 for  vertex function,
+  !! 1 for edge function, 2 for face function and 3 for bubble function).
+  !! `infoKeys[0].second' gives the order of the function associated with the
+  !! key. Warning: this is an experimental feature and will probably change in a
+  !! future release.
+  subroutine gmshModelMeshGetKeysInformation(typeKeys, &
+                                             entityKeys, &
+                                             elementType, &
+                                             functionSpaceType, &
+                                             infoKeys, &
+                                             ierr)
+    interface
+    subroutine C_API(api_typeKeys_, &
+                     api_typeKeys_n_, &
+                     api_entityKeys_, &
+                     api_entityKeys_n_, &
+                     elementType, &
+                     functionSpaceType, &
+                     api_infoKeys_, &
+                     api_infoKeys_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetKeysInformation")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_typeKeys_
+      integer(c_size_t), value, intent(in) :: api_typeKeys_n_
+      integer(c_size_t), dimension(*) :: api_entityKeys_
+      integer(c_size_t), value, intent(in) :: api_entityKeys_n_
+      integer(c_int), value, intent(in) :: elementType
+      character(len=1, kind=c_char), dimension(*), intent(in) :: functionSpaceType
+      type(c_ptr), intent(out) :: api_infoKeys_
+      integer(c_size_t), intent(out) :: api_infoKeys_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:), intent(in) :: typeKeys
+    integer(c_size_t), dimension(:), intent(in) :: entityKeys
+    integer, intent(in) :: elementType
+    character(len=*), intent(in) :: functionSpaceType
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: infoKeys
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_infoKeys_
+    integer(c_size_t) :: api_infoKeys_n_
+    call C_API(api_typeKeys_=typeKeys, &
+         api_typeKeys_n_=size_gmsh_int(typeKeys), &
+         api_entityKeys_=entityKeys, &
+         api_entityKeys_n_=size_gmsh_size(entityKeys), &
+         elementType=int(elementType, c_int), &
+         functionSpaceType=istring_(functionSpaceType), &
+         api_infoKeys_=api_infoKeys_, &
+         api_infoKeys_n_=api_infoKeys_n_, &
+         ierr_=ierr)
+    ! Post processing
+    infoKeys = ovectorpair_(api_infoKeys_, &
+      api_infoKeys_n_)
+  end subroutine gmshModelMeshGetKeysInformation
+
+  !> Get the barycenters of all elements of type `elementType' classified on the
+  !! entity of tag `tag'. If `primary' is set, only the primary nodes of the
+  !! elements are taken into account for the barycenter calculation. If `fast'
+  !! is set, the function returns the sum of the primary node coordinates
+  !! (without normalizing by the number of nodes). If `tag' < 0, get the
+  !! barycenters for all entities. If `numTasks' > 1, only compute and return
+  !! the part of the data indexed by `task'.
+  subroutine gmshModelMeshGetBarycenters(elementType, &
+                                         tag, &
+                                         fast, &
+                                         primary, &
+                                         barycenters, &
+                                         task, &
+                                         numTasks, &
+                                         ierr)
+    interface
+    subroutine C_API(elementType, &
+                     tag, &
+                     fast, &
+                     primary, &
+                     api_barycenters_, &
+                     api_barycenters_n_, &
+                     task, &
+                     numTasks, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetBarycenters")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: elementType
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: fast
+      integer(c_int), value, intent(in) :: primary
+      type(c_ptr), intent(out) :: api_barycenters_
+      integer(c_size_t) :: api_barycenters_n_
+      integer(c_size_t), value, intent(in) :: task
+      integer(c_size_t), value, intent(in) :: numTasks
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: elementType
+    integer, intent(in) :: tag
+    logical, intent(in) :: fast
+    logical, intent(in) :: primary
+    real(c_double), dimension(:), allocatable, intent(out) :: barycenters
+    integer, intent(in), optional :: task
+    integer, intent(in), optional :: numTasks
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_barycenters_
+    integer(c_size_t) :: api_barycenters_n_
+    call C_API(elementType=int(elementType, c_int), &
+         tag=int(tag, c_int), &
+         fast=merge(1_c_int, 0_c_int, fast), &
+         primary=merge(1_c_int, 0_c_int, primary), &
+         api_barycenters_=api_barycenters_, &
+         api_barycenters_n_=api_barycenters_n_, &
+         task=optval_c_size_t(0, task), &
+         numTasks=optval_c_size_t(1, numTasks), &
+         ierr_=ierr)
+    ! Post processing
+    barycenters = ovectordouble_(api_barycenters_, &
+      api_barycenters_n_)
+  end subroutine gmshModelMeshGetBarycenters
+
+  !> Preallocate data before calling `getBarycenters' with `numTasks' > 1. For C
+  !! and C++ only.
+  subroutine gmshModelMeshPreallocateBarycenters(elementType, &
+                                                 barycenters, &
+                                                 tag, &
+                                                 ierr)
+    interface
+    subroutine C_API(elementType, &
+                     api_barycenters_, &
+                     api_barycenters_n_, &
+                     tag, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshPreallocateBarycenters")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: elementType
+      type(c_ptr), intent(out) :: api_barycenters_
+      integer(c_size_t) :: api_barycenters_n_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: elementType
+    real(c_double), dimension(:), allocatable, intent(out) :: barycenters
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_barycenters_
+    integer(c_size_t) :: api_barycenters_n_
+    call C_API(elementType=int(elementType, c_int), &
+         api_barycenters_=api_barycenters_, &
+         api_barycenters_n_=api_barycenters_n_, &
+         tag=optval_c_int(-1, tag), &
+         ierr_=ierr)
+    ! Post processing
+    barycenters = ovectordouble_(api_barycenters_, &
+      api_barycenters_n_)
+  end subroutine gmshModelMeshPreallocateBarycenters
+
+  !> Get the nodes on the edges of all elements of type `elementType' classified
+  !! on the entity of tag `tag'. `nodeTags' contains the node tags of the edges
+  !! for all the elements: [e1a1n1, e1a1n2, e1a2n1, ...]. Data is returned by
+  !! element, with elements in the same order as in `getElements' and
+  !! `getElementsByType'. If `primary' is set, only the primary (begin/end)
+  !! nodes of the edges are returned. If `tag' < 0, get the edge nodes for all
+  !! entities. If `numTasks' > 1, only compute and return the part of the data
+  !! indexed by `task'.
+  subroutine gmshModelMeshGetElementEdgeNodes(elementType, &
+                                              nodeTags, &
+                                              tag, &
+                                              primary, &
+                                              task, &
+                                              numTasks, &
+                                              ierr)
+    interface
+    subroutine C_API(elementType, &
+                     api_nodeTags_, &
+                     api_nodeTags_n_, &
+                     tag, &
+                     primary, &
+                     task, &
+                     numTasks, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetElementEdgeNodes")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: elementType
+      type(c_ptr), intent(out) :: api_nodeTags_
+      integer(c_size_t), intent(out) :: api_nodeTags_n_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: primary
+      integer(c_size_t), value, intent(in) :: task
+      integer(c_size_t), value, intent(in) :: numTasks
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: elementType
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: nodeTags
+    integer, intent(in), optional :: tag
+    logical, intent(in), optional :: primary
+    integer, intent(in), optional :: task
+    integer, intent(in), optional :: numTasks
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_nodeTags_
+    integer(c_size_t) :: api_nodeTags_n_
+    call C_API(elementType=int(elementType, c_int), &
+         api_nodeTags_=api_nodeTags_, &
+         api_nodeTags_n_=api_nodeTags_n_, &
+         tag=optval_c_int(-1, tag), &
+         primary=optval_c_bool(.false., primary), &
+         task=optval_c_size_t(0, task), &
+         numTasks=optval_c_size_t(1, numTasks), &
+         ierr_=ierr)
+    ! Post processing
+    nodeTags = ovectorsize_(api_nodeTags_, &
+      api_nodeTags_n_)
+  end subroutine gmshModelMeshGetElementEdgeNodes
+
+  !> Get the nodes on the faces of type `faceType' (3 for triangular faces, 4
+  !! for quadrangular faces) of all elements of type `elementType' classified on
+  !! the entity of tag `tag'. `nodeTags' contains the node tags of the faces for
+  !! all elements: [e1f1n1, ..., e1f1nFaceType, e1f2n1, ...]. Data is returned
+  !! by element, with elements in the same order as in `getElements' and
+  !! `getElementsByType'. If `primary' is set, only the primary (corner) nodes
+  !! of the faces are returned. If `tag' < 0, get the face nodes for all
+  !! entities. If `numTasks' > 1, only compute and return the part of the data
+  !! indexed by `task'.
+  subroutine gmshModelMeshGetElementFaceNodes(elementType, &
+                                              faceType, &
+                                              nodeTags, &
+                                              tag, &
+                                              primary, &
+                                              task, &
+                                              numTasks, &
+                                              ierr)
+    interface
+    subroutine C_API(elementType, &
+                     faceType, &
+                     api_nodeTags_, &
+                     api_nodeTags_n_, &
+                     tag, &
+                     primary, &
+                     task, &
+                     numTasks, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetElementFaceNodes")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: elementType
+      integer(c_int), value, intent(in) :: faceType
+      type(c_ptr), intent(out) :: api_nodeTags_
+      integer(c_size_t), intent(out) :: api_nodeTags_n_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: primary
+      integer(c_size_t), value, intent(in) :: task
+      integer(c_size_t), value, intent(in) :: numTasks
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: elementType
+    integer, intent(in) :: faceType
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: nodeTags
+    integer, intent(in), optional :: tag
+    logical, intent(in), optional :: primary
+    integer, intent(in), optional :: task
+    integer, intent(in), optional :: numTasks
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_nodeTags_
+    integer(c_size_t) :: api_nodeTags_n_
+    call C_API(elementType=int(elementType, c_int), &
+         faceType=int(faceType, c_int), &
+         api_nodeTags_=api_nodeTags_, &
+         api_nodeTags_n_=api_nodeTags_n_, &
+         tag=optval_c_int(-1, tag), &
+         primary=optval_c_bool(.false., primary), &
+         task=optval_c_size_t(0, task), &
+         numTasks=optval_c_size_t(1, numTasks), &
+         ierr_=ierr)
+    ! Post processing
+    nodeTags = ovectorsize_(api_nodeTags_, &
+      api_nodeTags_n_)
+  end subroutine gmshModelMeshGetElementFaceNodes
+
+  !> Get the ghost elements `elementTags' and their associated `partitions'
+  !! stored in the ghost entity of dimension `dim' and tag `tag'.
+  subroutine gmshModelMeshGetGhostElements(dim, &
+                                           tag, &
+                                           elementTags, &
+                                           partitions, &
+                                           ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     api_elementTags_, &
+                     api_elementTags_n_, &
+                     api_partitions_, &
+                     api_partitions_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetGhostElements")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      type(c_ptr), intent(out) :: api_elementTags_
+      integer(c_size_t), intent(out) :: api_elementTags_n_
+      type(c_ptr), intent(out) :: api_partitions_
+      integer(c_size_t), intent(out) :: api_partitions_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: elementTags
+    integer(c_int), dimension(:), allocatable, intent(out) :: partitions
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_elementTags_
+    integer(c_size_t) :: api_elementTags_n_
+    type(c_ptr) :: api_partitions_
+    integer(c_size_t) :: api_partitions_n_
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         api_elementTags_=api_elementTags_, &
+         api_elementTags_n_=api_elementTags_n_, &
+         api_partitions_=api_partitions_, &
+         api_partitions_n_=api_partitions_n_, &
+         ierr_=ierr)
+    ! Post processing
+    elementTags = ovectorsize_(api_elementTags_, &
+      api_elementTags_n_)
+    partitions = ovectorint_(api_partitions_, &
+      api_partitions_n_)
+  end subroutine gmshModelMeshGetGhostElements
+
+  !> Set a mesh size constraint on the model entities `dimTags'. Currently only
+  !! entities of dimension 0 (points) are handled.
+  subroutine gmshModelMeshSetSize(dimTags, &
+                                  size, &
+                                  ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     size, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshSetSize")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      real(c_double), value, intent(in) :: size
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    real(c_double), intent(in) :: size
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         size=real(size, c_double), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshSetSize
+
+  !> Get the mesh size constraints (if any) associated with the model entities
+  !! `dimTags'. A zero entry in the output `sizes' vector indicates that no size
+  !! constraint is specified on the corresponding entity.
+  subroutine gmshModelMeshGetSizes(dimTags, &
+                                   sizes, &
+                                   ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     api_sizes_, &
+                     api_sizes_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetSizes")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      type(c_ptr), intent(out) :: api_sizes_
+      integer(c_size_t) :: api_sizes_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    real(c_double), dimension(:), allocatable, intent(out) :: sizes
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_sizes_
+    integer(c_size_t) :: api_sizes_n_
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         api_sizes_=api_sizes_, &
+         api_sizes_n_=api_sizes_n_, &
+         ierr_=ierr)
+    ! Post processing
+    sizes = ovectordouble_(api_sizes_, &
+      api_sizes_n_)
+  end subroutine gmshModelMeshGetSizes
+
+  !> Set mesh size constraints at the given parametric points `parametricCoord'
+  !! on the model entity of dimension `dim' and tag `tag'. Currently only
+  !! entities of dimension 1 (lines) are handled.
+  subroutine gmshModelMeshSetSizeAtParametricPoints(dim, &
+                                                    tag, &
+                                                    parametricCoord, &
+                                                    sizes, &
+                                                    ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     api_parametricCoord_, &
+                     api_parametricCoord_n_, &
+                     api_sizes_, &
+                     api_sizes_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshSetSizeAtParametricPoints")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      real(c_double), dimension(*) :: api_parametricCoord_
+      integer(c_size_t), value, intent(in) :: api_parametricCoord_n_
+      real(c_double), dimension(*) :: api_sizes_
+      integer(c_size_t), value, intent(in) :: api_sizes_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    real(c_double), dimension(:), intent(in) :: parametricCoord
+    real(c_double), dimension(:), intent(in) :: sizes
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         api_parametricCoord_=parametricCoord, &
+         api_parametricCoord_n_=size_gmsh_double(parametricCoord), &
+         api_sizes_=sizes, &
+         api_sizes_n_=size_gmsh_double(sizes), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshSetSizeAtParametricPoints
+
+  !> Set a mesh size callback for the current model. The callback function
+  !! should take six arguments as input (`dim', `tag', `x', `y', `z' and `lc').
+  !! The first two integer arguments correspond to the dimension `dim' and tag
+  !! `tag' of the entity being meshed. The next four double precision arguments
+  !! correspond to the coordinates `x', `y' and `z' around which to prescribe
+  !! the mesh size and to the mesh size `lc' that would be prescribed if the
+  !! callback had not been called. The callback function should return a double
+  !! precision number specifying the desired mesh size; returning `lc' is
+  !! equivalent to a no-op.
+  subroutine gmshModelMeshSetSizeCallback(callback, &
+                                          ierr)
+    interface
+    subroutine C_API(callback, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshSetSizeCallback")
+      use, intrinsic :: iso_c_binding
+      type(c_funptr), value, intent(in) :: callback
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    type(c_funptr), value, intent(in) :: callback
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(callback=callback, &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshSetSizeCallback
+
+  !> Remove the mesh size callback from the current model.
+  subroutine gmshModelMeshRemoveSizeCallback(ierr)
+    interface
+    subroutine C_API(ierr_) &
+      bind(C, name="gmshModelMeshRemoveSizeCallback")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshRemoveSizeCallback
+
+  !> Set a transfinite meshing constraint on the curve `tag', with `numNodes'
+  !! nodes distributed according to `meshType' and `coef'. Currently supported
+  !! types are "Progression" (geometrical progression with power `coef'), "Bump"
+  !! (refinement toward both extremities of the curve) and "Beta" (beta law).
+  subroutine gmshModelMeshSetTransfiniteCurve(tag, &
+                                              numNodes, &
+                                              meshType, &
+                                              coef, &
+                                              ierr)
+    interface
+    subroutine C_API(tag, &
+                     numNodes, &
+                     meshType, &
+                     coef, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshSetTransfiniteCurve")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: numNodes
+      character(len=1, kind=c_char), dimension(*), intent(in), optional :: meshType
+      real(c_double), value, intent(in) :: coef
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    integer, intent(in) :: numNodes
+    character(len=*), intent(in), optional :: meshType
+    real(c_double), intent(in), optional :: coef
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(tag=int(tag, c_int), &
+         numNodes=int(numNodes, c_int), &
+         meshType=istring_(optval_c_str("Progression", meshType)), &
+         coef=optval_c_double(1., coef), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshSetTransfiniteCurve
+
+  !> Set 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.
+  subroutine gmshModelMeshSetTransfiniteSurface(tag, &
+                                                arrangement, &
+                                                cornerTags, &
+                                                ierr)
+    interface
+    subroutine C_API(tag, &
+                     arrangement, &
+                     api_cornerTags_, &
+                     api_cornerTags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshSetTransfiniteSurface")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      character(len=1, kind=c_char), dimension(*), intent(in), optional :: arrangement
+      integer(c_int), dimension(*), optional :: api_cornerTags_
+      integer(c_size_t), value, intent(in) :: api_cornerTags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    character(len=*), intent(in), optional :: arrangement
+    integer(c_int), dimension(:), intent(in), optional :: cornerTags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(tag=int(tag, c_int), &
+         arrangement=istring_(optval_c_str("Left", arrangement)), &
+         api_cornerTags_=cornerTags, &
+         api_cornerTags_n_=size_gmsh_int(cornerTags), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshSetTransfiniteSurface
+
+  !> Set a transfinite meshing constraint on the surface `tag'. `cornerTags' can
+  !! be used to specify the (6 or 8) corners of the transfinite interpolation
+  !! explicitly.
+  subroutine gmshModelMeshSetTransfiniteVolume(tag, &
+                                               cornerTags, &
+                                               ierr)
+    interface
+    subroutine C_API(tag, &
+                     api_cornerTags_, &
+                     api_cornerTags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshSetTransfiniteVolume")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), dimension(*), optional :: api_cornerTags_
+      integer(c_size_t), value, intent(in) :: api_cornerTags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    integer(c_int), dimension(:), intent(in), optional :: cornerTags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(tag=int(tag, c_int), &
+         api_cornerTags_=cornerTags, &
+         api_cornerTags_n_=size_gmsh_int(cornerTags), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshSetTransfiniteVolume
+
+  !> Set transfinite meshing constraints on the model entities in `dimTag'.
+  !! Transfinite meshing constraints are added to the curves of the quadrangular
+  !! surfaces and to the faces of 6-sided volumes. Quadragular faces with a
+  !! corner angle superior to `cornerAngle' (in radians) are ignored. The number
+  !! of points is automatically determined from the sizing constraints. If
+  !! `dimTag' is empty, the constraints are applied to all entities in the
+  !! model. If `recombine' is true, the recombine flag is automatically set on
+  !! the transfinite surfaces.
+  subroutine gmshModelMeshSetTransfiniteAutomatic(dimTags, &
+                                                  cornerAngle, &
+                                                  recombine, &
+                                                  ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     cornerAngle, &
+                     recombine, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshSetTransfiniteAutomatic")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*), optional :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      real(c_double), value, intent(in) :: cornerAngle
+      integer(c_int), value, intent(in) :: recombine
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in), optional :: dimTags
+    real(c_double), intent(in), optional :: cornerAngle
+    logical, intent(in), optional :: recombine
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         cornerAngle=optval_c_double(2.35, cornerAngle), &
+         recombine=optval_c_bool(.true., recombine), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshSetTransfiniteAutomatic
+
+  !> Set a recombination meshing constraint on the model entity of dimension
+  !! `dim' and tag `tag'. Currently only entities of dimension 2 (to recombine
+  !! triangles into quadrangles) are supported; `angle' specifies the threshold
+  !! angle for the simple recombination algorithm..
+  subroutine gmshModelMeshSetRecombine(dim, &
+                                       tag, &
+                                       angle, &
+                                       ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     angle, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshSetRecombine")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      real(c_double), value, intent(in) :: angle
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    real(c_double), intent(in), optional :: angle
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         angle=optval_c_double(45., angle), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshSetRecombine
+
+  !> Set a smoothing meshing constraint on the model entity of dimension `dim'
+  !! and tag `tag'. `val' iterations of a Laplace smoother are applied.
+  subroutine gmshModelMeshSetSmoothing(dim, &
+                                       tag, &
+                                       val, &
+                                       ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     val, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshSetSmoothing")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: val
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    integer, intent(in) :: val
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         val=int(val, c_int), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshSetSmoothing
+
+  !> Set a reverse meshing constraint on the model 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 geometry). If `val' is false, the mesh is left
+  !! as-is.
+  subroutine gmshModelMeshSetReverse(dim, &
+                                     tag, &
+                                     val, &
+                                     ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     val, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshSetReverse")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: val
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    logical, intent(in), optional :: val
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         val=optval_c_bool(.true., val), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshSetReverse
+
+  !> Set the meshing algorithm on the model entity of dimension `dim' and tag
+  !! `tag'. Currently only supported for `dim' == 2.
+  subroutine gmshModelMeshSetAlgorithm(dim, &
+                                       tag, &
+                                       val, &
+                                       ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     val, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshSetAlgorithm")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: val
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    integer, intent(in) :: val
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         val=int(val, c_int), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshSetAlgorithm
+
+  !> Force the mesh size to be extended from the boundary, or not, for the model
+  !! entity of dimension `dim' and tag `tag'. Currently only supported for `dim'
+  !! == 2.
+  subroutine gmshModelMeshSetSizeFromBoundary(dim, &
+                                              tag, &
+                                              val, &
+                                              ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     val, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshSetSizeFromBoundary")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: val
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    integer, intent(in) :: val
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         val=int(val, c_int), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshSetSizeFromBoundary
+
+  !> Set a compound meshing constraint on the model entities of dimension `dim'
+  !! and tags `tags'. During meshing, compound entities are treated as a single
+  !! discrete entity, which is automatically reparametrized.
+  subroutine gmshModelMeshSetCompound(dim, &
+                                      tags, &
+                                      ierr)
+    interface
+    subroutine C_API(dim, &
+                     api_tags_, &
+                     api_tags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshSetCompound")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), dimension(*) :: api_tags_
+      integer(c_size_t), value, intent(in) :: api_tags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer(c_int), dimension(:), intent(in) :: tags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=int(dim, c_int), &
+         api_tags_=tags, &
+         api_tags_n_=size_gmsh_int(tags), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshSetCompound
+
+  !> Set meshing constraints on the bounding surfaces of the volume of tag `tag'
+  !! so that all surfaces are oriented with outward pointing normals; and if a
+  !! mesh already exists, reorient it. Currently only available with the
+  !! OpenCASCADE kernel, as it relies on the STL triangulation.
+  subroutine gmshModelMeshSetOutwardOrientation(tag, &
+                                                ierr)
+    interface
+    subroutine C_API(tag, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshSetOutwardOrientation")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(tag=int(tag, c_int), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshSetOutwardOrientation
+
+  !> Remove all meshing constraints from the model entities `dimTags'. If
+  !! `dimTags' is empty, remove all constraings.
+  subroutine gmshModelMeshRemoveConstraints(dimTags, &
+                                            ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshRemoveConstraints")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*), optional :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in), optional :: dimTags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshRemoveConstraints
+
+  !> Embed the model entities of dimension `dim' and tags `tags' in the
+  !! (`inDim', `inTag') model entity. The dimension `dim' can 0, 1 or 2 and must
+  !! be strictly smaller than `inDim', which must be either 2 or 3. The embedded
+  !! entities should not intersect each other or be part of the boundary of the
+  !! entity `inTag', whose mesh will conform to the mesh of the embedded
+  !! entities. With the OpenCASCADE kernel, if the `fragment' operation is
+  !! applied to entities of different dimensions, the lower dimensional entities
+  !! will be automatically embedded in the higher dimensional entities if they
+  !! are not on their boundary.
+  subroutine gmshModelMeshEmbed(dim, &
+                                tags, &
+                                inDim, &
+                                inTag, &
+                                ierr)
+    interface
+    subroutine C_API(dim, &
+                     api_tags_, &
+                     api_tags_n_, &
+                     inDim, &
+                     inTag, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshEmbed")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), dimension(*) :: api_tags_
+      integer(c_size_t), value, intent(in) :: api_tags_n_
+      integer(c_int), value, intent(in) :: inDim
+      integer(c_int), value, intent(in) :: inTag
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer(c_int), dimension(:), intent(in) :: tags
+    integer, intent(in) :: inDim
+    integer, intent(in) :: inTag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=int(dim, c_int), &
+         api_tags_=tags, &
+         api_tags_n_=size_gmsh_int(tags), &
+         inDim=int(inDim, c_int), &
+         inTag=int(inTag, c_int), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshEmbed
+
+  !> Remove embedded entities from the model entities `dimTags'. if `dim' is >=
+  !! 0, only remove embedded entities of the given dimension (e.g. embedded
+  !! points if `dim' == 0).
+  subroutine gmshModelMeshRemoveEmbedded(dimTags, &
+                                         dim, &
+                                         ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     dim, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshRemoveEmbedded")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    integer, intent(in), optional :: dim
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         dim=optval_c_int(-1, dim), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshRemoveEmbedded
+
+  !> Get the entities (if any) embedded in the model entity of dimension `dim'
+  !! and tag `tag'.
+  subroutine gmshModelMeshGetEmbedded(dim, &
+                                      tag, &
+                                      dimTags, &
+                                      ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     api_dimTags_, &
+                     api_dimTags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetEmbedded")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      type(c_ptr), intent(out) :: api_dimTags_
+      integer(c_size_t), intent(out) :: api_dimTags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: dimTags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_dimTags_
+    integer(c_size_t) :: api_dimTags_n_
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         api_dimTags_=api_dimTags_, &
+         api_dimTags_n_=api_dimTags_n_, &
+         ierr_=ierr)
+    ! Post processing
+    dimTags = ovectorpair_(api_dimTags_, &
+      api_dimTags_n_)
+  end subroutine gmshModelMeshGetEmbedded
+
+  !> Reorder the elements of type `elementType' classified on the entity of tag
+  !! `tag' according to `ordering'.
+  subroutine gmshModelMeshReorderElements(elementType, &
+                                          tag, &
+                                          ordering, &
+                                          ierr)
+    interface
+    subroutine C_API(elementType, &
+                     tag, &
+                     api_ordering_, &
+                     api_ordering_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshReorderElements")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: elementType
+      integer(c_int), value, intent(in) :: tag
+      integer(c_size_t), dimension(*) :: api_ordering_
+      integer(c_size_t), value, intent(in) :: api_ordering_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: elementType
+    integer, intent(in) :: tag
+    integer(c_size_t), dimension(:), intent(in) :: ordering
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(elementType=int(elementType, c_int), &
+         tag=int(tag, c_int), &
+         api_ordering_=ordering, &
+         api_ordering_n_=size_gmsh_size(ordering), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshReorderElements
+
+  !> Renumber the node tags in a continuous sequence.
+  subroutine gmshModelMeshRenumberNodes(ierr)
+    interface
+    subroutine C_API(ierr_) &
+      bind(C, name="gmshModelMeshRenumberNodes")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshRenumberNodes
+
+  !> Renumber the element tags in a continuous sequence.
+  subroutine gmshModelMeshRenumberElements(ierr)
+    interface
+    subroutine C_API(ierr_) &
+      bind(C, name="gmshModelMeshRenumberElements")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshRenumberElements
+
+  !> Set the meshes of the entities of dimension `dim' and tag `tags' as
+  !! periodic copies of the meshes of entities `tagsMaster', using the affine
+  !! transformation specified in `affineTransformation' (16 entries of a 4x4
+  !! matrix, by row). If used after meshing, generate the periodic node
+  !! correspondence information assuming the meshes of entities `tags'
+  !! effectively match the meshes of entities `tagsMaster' (useful for
+  !! structured and extruded meshes). Currently only available for @code{dim} ==
+  !! 1 and @code{dim} == 2.
+  subroutine gmshModelMeshSetPeriodic(dim, &
+                                      tags, &
+                                      tagsMaster, &
+                                      affineTransform, &
+                                      ierr)
+    interface
+    subroutine C_API(dim, &
+                     api_tags_, &
+                     api_tags_n_, &
+                     api_tagsMaster_, &
+                     api_tagsMaster_n_, &
+                     api_affineTransform_, &
+                     api_affineTransform_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshSetPeriodic")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), dimension(*) :: api_tags_
+      integer(c_size_t), value, intent(in) :: api_tags_n_
+      integer(c_int), dimension(*) :: api_tagsMaster_
+      integer(c_size_t), value, intent(in) :: api_tagsMaster_n_
+      real(c_double), dimension(*) :: api_affineTransform_
+      integer(c_size_t), value, intent(in) :: api_affineTransform_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer(c_int), dimension(:), intent(in) :: tags
+    integer(c_int), dimension(:), intent(in) :: tagsMaster
+    real(c_double), dimension(:), intent(in) :: affineTransform
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=int(dim, c_int), &
+         api_tags_=tags, &
+         api_tags_n_=size_gmsh_int(tags), &
+         api_tagsMaster_=tagsMaster, &
+         api_tagsMaster_n_=size_gmsh_int(tagsMaster), &
+         api_affineTransform_=affineTransform, &
+         api_affineTransform_n_=size_gmsh_double(affineTransform), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshSetPeriodic
+
+  !> Get master entities `tagsMaster' for the entities of dimension `dim' and
+  !! tags `tags'.
+  subroutine gmshModelMeshGetPeriodic(dim, &
+                                      tags, &
+                                      tagMaster, &
+                                      ierr)
+    interface
+    subroutine C_API(dim, &
+                     api_tags_, &
+                     api_tags_n_, &
+                     api_tagMaster_, &
+                     api_tagMaster_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetPeriodic")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), dimension(*) :: api_tags_
+      integer(c_size_t), value, intent(in) :: api_tags_n_
+      type(c_ptr), intent(out) :: api_tagMaster_
+      integer(c_size_t), intent(out) :: api_tagMaster_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer(c_int), dimension(:), intent(in) :: tags
+    integer(c_int), dimension(:), allocatable, intent(out) :: tagMaster
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_tagMaster_
+    integer(c_size_t) :: api_tagMaster_n_
+    call C_API(dim=int(dim, c_int), &
+         api_tags_=tags, &
+         api_tags_n_=size_gmsh_int(tags), &
+         api_tagMaster_=api_tagMaster_, &
+         api_tagMaster_n_=api_tagMaster_n_, &
+         ierr_=ierr)
+    ! Post processing
+    tagMaster = ovectorint_(api_tagMaster_, &
+      api_tagMaster_n_)
+  end subroutine gmshModelMeshGetPeriodic
+
+  !> Get the master entity `tagMaster', the node tags `nodeTags' and their
+  !! corresponding master node tags `nodeTagsMaster', and the affine transform
+  !! `affineTransform' for the entity of dimension `dim' and tag `tag'. If
+  !! `includeHighOrderNodes' is set, include high-order nodes in the returned
+  !! data.
+  subroutine gmshModelMeshGetPeriodicNodes(dim, &
+                                           tag, &
+                                           tagMaster, &
+                                           nodeTags, &
+                                           nodeTagsMaster, &
+                                           affineTransform, &
+                                           includeHighOrderNodes, &
+                                           ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     tagMaster, &
+                     api_nodeTags_, &
+                     api_nodeTags_n_, &
+                     api_nodeTagsMaster_, &
+                     api_nodeTagsMaster_n_, &
+                     api_affineTransform_, &
+                     api_affineTransform_n_, &
+                     includeHighOrderNodes, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetPeriodicNodes")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int) :: tagMaster
+      type(c_ptr), intent(out) :: api_nodeTags_
+      integer(c_size_t), intent(out) :: api_nodeTags_n_
+      type(c_ptr), intent(out) :: api_nodeTagsMaster_
+      integer(c_size_t), intent(out) :: api_nodeTagsMaster_n_
+      type(c_ptr), intent(out) :: api_affineTransform_
+      integer(c_size_t) :: api_affineTransform_n_
+      integer(c_int), value, intent(in) :: includeHighOrderNodes
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    integer(c_int) :: tagMaster
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: nodeTags
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: nodeTagsMaster
+    real(c_double), dimension(:), allocatable, intent(out) :: affineTransform
+    logical, intent(in), optional :: includeHighOrderNodes
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_nodeTags_
+    integer(c_size_t) :: api_nodeTags_n_
+    type(c_ptr) :: api_nodeTagsMaster_
+    integer(c_size_t) :: api_nodeTagsMaster_n_
+    type(c_ptr) :: api_affineTransform_
+    integer(c_size_t) :: api_affineTransform_n_
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         tagMaster=tagMaster, &
+         api_nodeTags_=api_nodeTags_, &
+         api_nodeTags_n_=api_nodeTags_n_, &
+         api_nodeTagsMaster_=api_nodeTagsMaster_, &
+         api_nodeTagsMaster_n_=api_nodeTagsMaster_n_, &
+         api_affineTransform_=api_affineTransform_, &
+         api_affineTransform_n_=api_affineTransform_n_, &
+         includeHighOrderNodes=optval_c_bool(.false., includeHighOrderNodes), &
+         ierr_=ierr)
+    ! Post processing
+    nodeTags = ovectorsize_(api_nodeTags_, &
+      api_nodeTags_n_)
+    nodeTagsMaster = ovectorsize_(api_nodeTagsMaster_, &
+      api_nodeTagsMaster_n_)
+    affineTransform = ovectordouble_(api_affineTransform_, &
+      api_affineTransform_n_)
+  end subroutine gmshModelMeshGetPeriodicNodes
+
+  !> Get the master entity `tagMaster' and the key pairs (`typeKeyMaster',
+  !! `entityKeyMaster') corresponding to the entity `tag' and the key pairs
+  !! (`typeKey', `entityKey') for the elements of type `elementType' and
+  !! function space type `functionSpaceType'. If `returnCoord' is set, the
+  !! `coord' and `coordMaster' vectors contain the x, y, z coordinates locating
+  !! basis functions for sorting purposes.
+  subroutine gmshModelMeshGetPeriodicKeys(elementType, &
+                                          functionSpaceType, &
+                                          tag, &
+                                          tagMaster, &
+                                          typeKeys, &
+                                          typeKeysMaster, &
+                                          entityKeys, &
+                                          entityKeysMaster, &
+                                          coord, &
+                                          coordMaster, &
+                                          returnCoord, &
+                                          ierr)
+    interface
+    subroutine C_API(elementType, &
+                     functionSpaceType, &
+                     tag, &
+                     tagMaster, &
+                     api_typeKeys_, &
+                     api_typeKeys_n_, &
+                     api_typeKeysMaster_, &
+                     api_typeKeysMaster_n_, &
+                     api_entityKeys_, &
+                     api_entityKeys_n_, &
+                     api_entityKeysMaster_, &
+                     api_entityKeysMaster_n_, &
+                     api_coord_, &
+                     api_coord_n_, &
+                     api_coordMaster_, &
+                     api_coordMaster_n_, &
+                     returnCoord, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetPeriodicKeys")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: elementType
+      character(len=1, kind=c_char), dimension(*), intent(in) :: functionSpaceType
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int) :: tagMaster
+      type(c_ptr), intent(out) :: api_typeKeys_
+      integer(c_size_t), intent(out) :: api_typeKeys_n_
+      type(c_ptr), intent(out) :: api_typeKeysMaster_
+      integer(c_size_t), intent(out) :: api_typeKeysMaster_n_
+      type(c_ptr), intent(out) :: api_entityKeys_
+      integer(c_size_t), intent(out) :: api_entityKeys_n_
+      type(c_ptr), intent(out) :: api_entityKeysMaster_
+      integer(c_size_t), intent(out) :: api_entityKeysMaster_n_
+      type(c_ptr), intent(out) :: api_coord_
+      integer(c_size_t) :: api_coord_n_
+      type(c_ptr), intent(out) :: api_coordMaster_
+      integer(c_size_t) :: api_coordMaster_n_
+      integer(c_int), value, intent(in) :: returnCoord
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: elementType
+    character(len=*), intent(in) :: functionSpaceType
+    integer, intent(in) :: tag
+    integer(c_int) :: tagMaster
+    integer(c_int), dimension(:), allocatable, intent(out) :: typeKeys
+    integer(c_int), dimension(:), allocatable, intent(out) :: typeKeysMaster
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: entityKeys
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: entityKeysMaster
+    real(c_double), dimension(:), allocatable, intent(out) :: coord
+    real(c_double), dimension(:), allocatable, intent(out) :: coordMaster
+    logical, intent(in), optional :: returnCoord
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_typeKeys_
+    integer(c_size_t) :: api_typeKeys_n_
+    type(c_ptr) :: api_typeKeysMaster_
+    integer(c_size_t) :: api_typeKeysMaster_n_
+    type(c_ptr) :: api_entityKeys_
+    integer(c_size_t) :: api_entityKeys_n_
+    type(c_ptr) :: api_entityKeysMaster_
+    integer(c_size_t) :: api_entityKeysMaster_n_
+    type(c_ptr) :: api_coord_
+    integer(c_size_t) :: api_coord_n_
+    type(c_ptr) :: api_coordMaster_
+    integer(c_size_t) :: api_coordMaster_n_
+    call C_API(elementType=int(elementType, c_int), &
+         functionSpaceType=istring_(functionSpaceType), &
+         tag=int(tag, c_int), &
+         tagMaster=tagMaster, &
+         api_typeKeys_=api_typeKeys_, &
+         api_typeKeys_n_=api_typeKeys_n_, &
+         api_typeKeysMaster_=api_typeKeysMaster_, &
+         api_typeKeysMaster_n_=api_typeKeysMaster_n_, &
+         api_entityKeys_=api_entityKeys_, &
+         api_entityKeys_n_=api_entityKeys_n_, &
+         api_entityKeysMaster_=api_entityKeysMaster_, &
+         api_entityKeysMaster_n_=api_entityKeysMaster_n_, &
+         api_coord_=api_coord_, &
+         api_coord_n_=api_coord_n_, &
+         api_coordMaster_=api_coordMaster_, &
+         api_coordMaster_n_=api_coordMaster_n_, &
+         returnCoord=optval_c_bool(.true., returnCoord), &
+         ierr_=ierr)
+    ! Post processing
+    typeKeys = ovectorint_(api_typeKeys_, &
+      api_typeKeys_n_)
+    typeKeysMaster = ovectorint_(api_typeKeysMaster_, &
+      api_typeKeysMaster_n_)
+    entityKeys = ovectorsize_(api_entityKeys_, &
+      api_entityKeys_n_)
+    entityKeysMaster = ovectorsize_(api_entityKeysMaster_, &
+      api_entityKeysMaster_n_)
+    coord = ovectordouble_(api_coord_, &
+      api_coord_n_)
+    coordMaster = ovectordouble_(api_coordMaster_, &
+      api_coordMaster_n_)
+  end subroutine gmshModelMeshGetPeriodicKeys
+
+  !> Import the model STL representation (if available) as the current mesh.
+  subroutine gmshModelMeshImportStl(ierr)
+    interface
+    subroutine C_API(ierr_) &
+      bind(C, name="gmshModelMeshImportStl")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshImportStl
+
+  !> Get the `tags' of any duplicate nodes in the mesh of the entities
+  !! `dimTags'. If `dimTags' is empty, consider the whole mesh.
+  subroutine gmshModelMeshGetDuplicateNodes(tags, &
+                                            dimTags, &
+                                            ierr)
+    interface
+    subroutine C_API(api_tags_, &
+                     api_tags_n_, &
+                     api_dimTags_, &
+                     api_dimTags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshGetDuplicateNodes")
+      use, intrinsic :: iso_c_binding
+      type(c_ptr), intent(out) :: api_tags_
+      integer(c_size_t), intent(out) :: api_tags_n_
+      integer(c_int), dimension(*), optional :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: tags
+    integer(c_int), dimension(:,:), intent(in), optional :: dimTags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_tags_
+    integer(c_size_t) :: api_tags_n_
+    call C_API(api_tags_=api_tags_, &
+         api_tags_n_=api_tags_n_, &
+         api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         ierr_=ierr)
+    ! Post processing
+    tags = ovectorsize_(api_tags_, &
+      api_tags_n_)
+  end subroutine gmshModelMeshGetDuplicateNodes
+
+  !> Remove duplicate nodes in the mesh of the entities `dimTags'. If `dimTags'
+  !! is empty, consider the whole mesh.
+  subroutine gmshModelMeshRemoveDuplicateNodes(dimTags, &
+                                               ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshRemoveDuplicateNodes")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*), optional :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in), optional :: dimTags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshRemoveDuplicateNodes
+
+  !> Remove duplicate elements (defined by the same nodes, in the same entity)
+  !! in the mesh of the entities `dimTags'. If `dimTags' is empty, consider the
+  !! whole mesh.
+  subroutine gmshModelMeshRemoveDuplicateElements(dimTags, &
+                                                  ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshRemoveDuplicateElements")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*), optional :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in), optional :: dimTags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshRemoveDuplicateElements
+
+  !> Split (into two triangles) all quadrangles in surface `tag' whose quality
+  !! is lower than `quality'. If `tag' < 0, split quadrangles in all surfaces.
+  subroutine gmshModelMeshSplitQuadrangles(quality, &
+                                           tag, &
+                                           ierr)
+    interface
+    subroutine C_API(quality, &
+                     tag, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshSplitQuadrangles")
+      use, intrinsic :: iso_c_binding
+      real(c_double), value, intent(in) :: quality
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    real(c_double), intent(in), optional :: quality
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(quality=optval_c_double(1., quality), &
+         tag=optval_c_int(-1, tag), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshSplitQuadrangles
+
+  !> Set the visibility of the elements of tags `elementTags' to `value'.
+  subroutine gmshModelMeshSetVisibility(elementTags, &
+                                        value, &
+                                        ierr)
+    interface
+    subroutine C_API(api_elementTags_, &
+                     api_elementTags_n_, &
+                     value, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshSetVisibility")
+      use, intrinsic :: iso_c_binding
+      integer(c_size_t), dimension(*) :: api_elementTags_
+      integer(c_size_t), value, intent(in) :: api_elementTags_n_
+      integer(c_int), value, intent(in) :: value
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_size_t), dimension(:), intent(in) :: elementTags
+    integer, intent(in) :: value
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_elementTags_=elementTags, &
+         api_elementTags_n_=size_gmsh_size(elementTags), &
+         value=int(value, c_int), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshSetVisibility
+
+  !> Classify ("color") the surface mesh based on the angle threshold `angle'
+  !! (in radians), and create new discrete surfaces, curves and points
+  !! accordingly. If `boundary' is set, also create discrete curves on the
+  !! boundary if the surface is open. If `forReparametrization' is set, create
+  !! curves and surfaces that can be reparametrized using a single map. If
+  !! `curveAngle' is less than Pi, also force curves to be split according to
+  !! `curveAngle'. If `exportDiscrete' is set, clear any built-in CAD kernel
+  !! entities and export the discrete entities in the built-in CAD kernel.
+  subroutine gmshModelMeshClassifySurfaces(angle, &
+                                           boundary, &
+                                           forReparametrization, &
+                                           curveAngle, &
+                                           exportDiscrete, &
+                                           ierr)
+    interface
+    subroutine C_API(angle, &
+                     boundary, &
+                     forReparametrization, &
+                     curveAngle, &
+                     exportDiscrete, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshClassifySurfaces")
+      use, intrinsic :: iso_c_binding
+      real(c_double), value, intent(in) :: angle
+      integer(c_int), value, intent(in) :: boundary
+      integer(c_int), value, intent(in) :: forReparametrization
+      real(c_double), value, intent(in) :: curveAngle
+      integer(c_int), value, intent(in) :: exportDiscrete
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    real(c_double), intent(in) :: angle
+    logical, intent(in), optional :: boundary
+    logical, intent(in), optional :: forReparametrization
+    real(c_double), intent(in), optional :: curveAngle
+    logical, intent(in), optional :: exportDiscrete
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(angle=real(angle, c_double), &
+         boundary=optval_c_bool(.true., boundary), &
+         forReparametrization=optval_c_bool(.false., forReparametrization), &
+         curveAngle=optval_c_double(M_PI, curveAngle), &
+         exportDiscrete=optval_c_bool(.true., exportDiscrete), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshClassifySurfaces
+
+  !> Create a geometry for the discrete entities `dimTags' (represented solely
+  !! by a mesh, without an underlying CAD description), i.e. create a
+  !! parametrization for discrete curves and surfaces, assuming that each can be
+  !! parametrized with a single map. If `dimTags' is empty, create a geometry
+  !! for all the discrete entities.
+  subroutine gmshModelMeshCreateGeometry(dimTags, &
+                                         ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshCreateGeometry")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*), optional :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in), optional :: dimTags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshCreateGeometry
+
+  !> Create a boundary representation from the mesh if the model does not have
+  !! one (e.g. when imported from mesh file formats with no BRep representation
+  !! of the underlying model). If `makeSimplyConnected' is set, enforce simply
+  !! connected discrete surfaces and volumes. If `exportDiscrete' is set, clear
+  !! any built-in CAD kernel entities and export the discrete entities in the
+  !! built-in CAD kernel.
+  subroutine gmshModelMeshCreateTopology(makeSimplyConnected, &
+                                         exportDiscrete, &
+                                         ierr)
+    interface
+    subroutine C_API(makeSimplyConnected, &
+                     exportDiscrete, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshCreateTopology")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: makeSimplyConnected
+      integer(c_int), value, intent(in) :: exportDiscrete
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    logical, intent(in), optional :: makeSimplyConnected
+    logical, intent(in), optional :: exportDiscrete
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(makeSimplyConnected=optval_c_bool(.true., makeSimplyConnected), &
+         exportDiscrete=optval_c_bool(.true., exportDiscrete), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshCreateTopology
+
+  !> Add a request to compute a basis representation for homology spaces (if
+  !! `type' == "Homology") or cohomology spaces (if `type' == "Cohomology"). The
+  !! computation domain is given in a list of physical group tags `domainTags';
+  !! if empty, the whole mesh is the domain. The computation subdomain for
+  !! relative (co)homology computation is given in a list of physical group tags
+  !! `subdomainTags'; if empty, absolute (co)homology is computed. The
+  !! dimensions of the (co)homology bases to be computed are given in the list
+  !! `dim'; if empty, all bases are computed. Resulting basis representation
+  !! (co)chains are stored as physical groups in the mesh. If the request is
+  !! added before mesh generation, the computation will be performed at the end
+  !! of the meshing pipeline.
+  subroutine gmshModelMeshAddHomologyRequest(type, &
+                                             domainTags, &
+                                             subdomainTags, &
+                                             dims, &
+                                             ierr)
+    interface
+    subroutine C_API(type, &
+                     api_domainTags_, &
+                     api_domainTags_n_, &
+                     api_subdomainTags_, &
+                     api_subdomainTags_n_, &
+                     api_dims_, &
+                     api_dims_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshAddHomologyRequest")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in), optional :: type
+      integer(c_int), dimension(*), optional :: api_domainTags_
+      integer(c_size_t), value, intent(in) :: api_domainTags_n_
+      integer(c_int), dimension(*), optional :: api_subdomainTags_
+      integer(c_size_t), value, intent(in) :: api_subdomainTags_n_
+      integer(c_int), dimension(*), optional :: api_dims_
+      integer(c_size_t), value, intent(in) :: api_dims_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in), optional :: type
+    integer(c_int), dimension(:), intent(in), optional :: domainTags
+    integer(c_int), dimension(:), intent(in), optional :: subdomainTags
+    integer(c_int), dimension(:), intent(in), optional :: dims
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(type=istring_(optval_c_str("Homology", type)), &
+         api_domainTags_=domainTags, &
+         api_domainTags_n_=size_gmsh_int(domainTags), &
+         api_subdomainTags_=subdomainTags, &
+         api_subdomainTags_n_=size_gmsh_int(subdomainTags), &
+         api_dims_=dims, &
+         api_dims_n_=size_gmsh_int(dims), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshAddHomologyRequest
+
+  !> Clear all (co)homology computation requests.
+  subroutine gmshModelMeshClearHomologyRequests(ierr)
+    interface
+    subroutine C_API(ierr_) &
+      bind(C, name="gmshModelMeshClearHomologyRequests")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshClearHomologyRequests
+
+  !> Perform the (co)homology computations requested by addHomologyRequest().
+  !! The newly created physical groups are returned in `dimTags'.
+  subroutine gmshModelMeshComputeHomology(dimTags, &
+                                          ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshComputeHomology")
+      use, intrinsic :: iso_c_binding
+      type(c_ptr), intent(out) :: api_dimTags_
+      integer(c_size_t), intent(out) :: api_dimTags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: dimTags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_dimTags_
+    integer(c_size_t) :: api_dimTags_n_
+    call C_API(api_dimTags_=api_dimTags_, &
+         api_dimTags_n_=api_dimTags_n_, &
+         ierr_=ierr)
+    ! Post processing
+    dimTags = ovectorpair_(api_dimTags_, &
+      api_dimTags_n_)
+  end subroutine gmshModelMeshComputeHomology
+
+  !> Compute a cross field for the current mesh. The function creates 3 views:
+  !! the H function, the Theta function and cross directions. Return the tags of
+  !! the views.
+  subroutine gmshModelMeshComputeCrossField(viewTags, &
+                                            ierr)
+    interface
+    subroutine C_API(api_viewTags_, &
+                     api_viewTags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshComputeCrossField")
+      use, intrinsic :: iso_c_binding
+      type(c_ptr), intent(out) :: api_viewTags_
+      integer(c_size_t), intent(out) :: api_viewTags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:), allocatable, intent(out) :: viewTags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_viewTags_
+    integer(c_size_t) :: api_viewTags_n_
+    call C_API(api_viewTags_=api_viewTags_, &
+         api_viewTags_n_=api_viewTags_n_, &
+         ierr_=ierr)
+    ! Post processing
+    viewTags = ovectorint_(api_viewTags_, &
+      api_viewTags_n_)
+  end subroutine gmshModelMeshComputeCrossField
+
+  !> Triangulate the points given in the `coord' vector as pairs of u, v
+  !! coordinates, and return the node tags (with numbering starting at 1) of the
+  !! resulting triangles in `tri'.
+  subroutine gmshModelMeshTriangulate(coord, &
+                                      tri, &
+                                      ierr)
+    interface
+    subroutine C_API(api_coord_, &
+                     api_coord_n_, &
+                     api_tri_, &
+                     api_tri_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshTriangulate")
+      use, intrinsic :: iso_c_binding
+      real(c_double), dimension(*) :: api_coord_
+      integer(c_size_t), value, intent(in) :: api_coord_n_
+      type(c_ptr), intent(out) :: api_tri_
+      integer(c_size_t), intent(out) :: api_tri_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    real(c_double), dimension(:), intent(in) :: coord
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: tri
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_tri_
+    integer(c_size_t) :: api_tri_n_
+    call C_API(api_coord_=coord, &
+         api_coord_n_=size_gmsh_double(coord), &
+         api_tri_=api_tri_, &
+         api_tri_n_=api_tri_n_, &
+         ierr_=ierr)
+    ! Post processing
+    tri = ovectorsize_(api_tri_, &
+      api_tri_n_)
+  end subroutine gmshModelMeshTriangulate
+
+  !> Tetrahedralize the points given in the `coord' vector as triplets of x, y,
+  !! z coordinates, and return the node tags (with numbering starting at 1) of
+  !! the resulting tetrahedra in `tetra'.
+  subroutine gmshModelMeshTetrahedralize(coord, &
+                                         tetra, &
+                                         ierr)
+    interface
+    subroutine C_API(api_coord_, &
+                     api_coord_n_, &
+                     api_tetra_, &
+                     api_tetra_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshTetrahedralize")
+      use, intrinsic :: iso_c_binding
+      real(c_double), dimension(*) :: api_coord_
+      integer(c_size_t), value, intent(in) :: api_coord_n_
+      type(c_ptr), intent(out) :: api_tetra_
+      integer(c_size_t), intent(out) :: api_tetra_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    real(c_double), dimension(:), intent(in) :: coord
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: tetra
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_tetra_
+    integer(c_size_t) :: api_tetra_n_
+    call C_API(api_coord_=coord, &
+         api_coord_n_=size_gmsh_double(coord), &
+         api_tetra_=api_tetra_, &
+         api_tetra_n_=api_tetra_n_, &
+         ierr_=ierr)
+    ! Post processing
+    tetra = ovectorsize_(api_tetra_, &
+      api_tetra_n_)
+  end subroutine gmshModelMeshTetrahedralize
+
+  !> Add a new mesh size field of type `fieldType'. If `tag' is positive, assign
+  !! the tag explicitly; otherwise a new tag is assigned automatically. Return
+  !! the field tag.
+  function gmshModelMeshFieldAdd(fieldType, &
+                                 tag, &
+                                 ierr)
+    interface
+    function C_API(fieldType, &
+                   tag, &
+                   ierr_) &
+      bind(C, name="gmshModelMeshFieldAdd")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      character(len=1, kind=c_char), dimension(*), intent(in) :: fieldType
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelMeshFieldAdd
+    character(len=*), intent(in) :: fieldType
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelMeshFieldAdd = C_API(fieldType=istring_(fieldType), &
+                            tag=optval_c_int(-1, tag), &
+                            ierr_=ierr)
+    ! Post processing
+  end function gmshModelMeshFieldAdd
+
+  !> Remove the field with tag `tag'.
+  subroutine gmshModelMeshFieldRemove(tag, &
+                                      ierr)
+    interface
+    subroutine C_API(tag, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshFieldRemove")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(tag=int(tag, c_int), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshFieldRemove
+
+  !> Get the list of all fields.
+  subroutine gmshModelMeshFieldList(tags, &
+                                    ierr)
+    interface
+    subroutine C_API(api_tags_, &
+                     api_tags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshFieldList")
+      use, intrinsic :: iso_c_binding
+      type(c_ptr), intent(out) :: api_tags_
+      integer(c_size_t), intent(out) :: api_tags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:), allocatable, intent(out) :: tags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_tags_
+    integer(c_size_t) :: api_tags_n_
+    call C_API(api_tags_=api_tags_, &
+         api_tags_n_=api_tags_n_, &
+         ierr_=ierr)
+    ! Post processing
+    tags = ovectorint_(api_tags_, &
+      api_tags_n_)
+  end subroutine gmshModelMeshFieldList
+
+  !> Get the type `fieldType' of the field with tag `tag'.
+  subroutine gmshModelMeshFieldGetType(tag, &
+                                       fileType, &
+                                       ierr)
+    interface
+    subroutine C_API(tag, &
+                     api_fileType_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshFieldGetType")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      character(kind=c_char), dimension(*) :: api_fileType_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    character(len=:), allocatable, intent(out) :: fileType
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(tag=int(tag, c_int), &
+         api_fileType_=fileType, &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshFieldGetType
+
+  !> Set the numerical option `option' to value `value' for field `tag'.
+  subroutine gmshModelMeshFieldSetNumber(tag, &
+                                         option, &
+                                         value, &
+                                         ierr)
+    interface
+    subroutine C_API(tag, &
+                     option, &
+                     value, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshFieldSetNumber")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      character(len=1, kind=c_char), dimension(*), intent(in) :: option
+      real(c_double), value, intent(in) :: value
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    character(len=*), intent(in) :: option
+    real(c_double), intent(in) :: value
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(tag=int(tag, c_int), &
+         option=istring_(option), &
+         value=real(value, c_double), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshFieldSetNumber
+
+  !> Get the value of the numerical option `option' for field `tag'.
+  subroutine gmshModelMeshFieldGetNumber(tag, &
+                                         option, &
+                                         value, &
+                                         ierr)
+    interface
+    subroutine C_API(tag, &
+                     option, &
+                     value, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshFieldGetNumber")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      character(len=1, kind=c_char), dimension(*), intent(in) :: option
+      real(c_double) :: value
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    character(len=*), intent(in) :: option
+    real(c_double) :: value
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(tag=int(tag, c_int), &
+         option=istring_(option), &
+         value=value, &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshFieldGetNumber
+
+  !> Set the string option `option' to value `value' for field `tag'.
+  subroutine gmshModelMeshFieldSetString(tag, &
+                                         option, &
+                                         value, &
+                                         ierr)
+    interface
+    subroutine C_API(tag, &
+                     option, &
+                     value, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshFieldSetString")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      character(len=1, kind=c_char), dimension(*), intent(in) :: option
+      character(len=1, kind=c_char), dimension(*), intent(in) :: value
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    character(len=*), intent(in) :: option
+    character(len=*), intent(in) :: value
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(tag=int(tag, c_int), &
+         option=istring_(option), &
+         value=istring_(value), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshFieldSetString
+
+  !> Get the value of the string option `option' for field `tag'.
+  subroutine gmshModelMeshFieldGetString(tag, &
+                                         option, &
+                                         value, &
+                                         ierr)
+    interface
+    subroutine C_API(tag, &
+                     option, &
+                     api_value_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshFieldGetString")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      character(len=1, kind=c_char), dimension(*), intent(in) :: option
+      character(kind=c_char), dimension(*) :: api_value_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    character(len=*), intent(in) :: option
+    character(len=:), allocatable, intent(out) :: value
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(tag=int(tag, c_int), &
+         option=istring_(option), &
+         api_value_=value, &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshFieldGetString
+
+  !> Set the numerical list option `option' to value `value' for field `tag'.
+  subroutine gmshModelMeshFieldSetNumbers(tag, &
+                                          option, &
+                                          value, &
+                                          ierr)
+    interface
+    subroutine C_API(tag, &
+                     option, &
+                     api_value_, &
+                     api_value_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshFieldSetNumbers")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      character(len=1, kind=c_char), dimension(*), intent(in) :: option
+      real(c_double), dimension(*) :: api_value_
+      integer(c_size_t), value, intent(in) :: api_value_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    character(len=*), intent(in) :: option
+    real(c_double), dimension(:), intent(in) :: value
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(tag=int(tag, c_int), &
+         option=istring_(option), &
+         api_value_=value, &
+         api_value_n_=size_gmsh_double(value), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshFieldSetNumbers
+
+  !> Get the value of the numerical list option `option' for field `tag'.
+  subroutine gmshModelMeshFieldGetNumbers(tag, &
+                                          option, &
+                                          value, &
+                                          ierr)
+    interface
+    subroutine C_API(tag, &
+                     option, &
+                     api_value_, &
+                     api_value_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshFieldGetNumbers")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      character(len=1, kind=c_char), dimension(*), intent(in) :: option
+      type(c_ptr), intent(out) :: api_value_
+      integer(c_size_t) :: api_value_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    character(len=*), intent(in) :: option
+    real(c_double), dimension(:), allocatable, intent(out) :: value
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_value_
+    integer(c_size_t) :: api_value_n_
+    call C_API(tag=int(tag, c_int), &
+         option=istring_(option), &
+         api_value_=api_value_, &
+         api_value_n_=api_value_n_, &
+         ierr_=ierr)
+    ! Post processing
+    value = ovectordouble_(api_value_, &
+      api_value_n_)
+  end subroutine gmshModelMeshFieldGetNumbers
+
+  !> Set the field `tag' as the background mesh size field.
+  subroutine gmshModelMeshFieldSetAsBackgroundMesh(tag, &
+                                                   ierr)
+    interface
+    subroutine C_API(tag, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshFieldSetAsBackgroundMesh")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(tag=int(tag, c_int), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshFieldSetAsBackgroundMesh
+
+  !> Set the field `tag' as a boundary layer size field.
+  subroutine gmshModelMeshFieldSetAsBoundaryLayer(tag, &
+                                                  ierr)
+    interface
+    subroutine C_API(tag, &
+                     ierr_) &
+      bind(C, name="gmshModelMeshFieldSetAsBoundaryLayer")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(tag=int(tag, c_int), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelMeshFieldSetAsBoundaryLayer
+
+  !> Add a geometrical point in the built-in CAD representation, at coordinates
+  !! (`x', `y', `z'). If `meshSize' is > 0, add a meshing constraint at that
+  !! point. If `tag' is positive, set the tag explicitly; otherwise a new tag is
+  !! selected automatically. Return the tag of the point. (Note that the point
+  !! will be added in the current model only after `synchronize' is called. This
+  !! behavior holds for all the entities added in the geo module.)
+  function gmshModelGeoAddPoint(x, &
+                                y, &
+                                z, &
+                                meshSize, &
+                                tag, &
+                                ierr)
+    interface
+    function C_API(x, &
+                   y, &
+                   z, &
+                   meshSize, &
+                   tag, &
+                   ierr_) &
+      bind(C, name="gmshModelGeoAddPoint")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      real(c_double), value, intent(in) :: x
+      real(c_double), value, intent(in) :: y
+      real(c_double), value, intent(in) :: z
+      real(c_double), value, intent(in) :: meshSize
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelGeoAddPoint
+    real(c_double), intent(in) :: x
+    real(c_double), intent(in) :: y
+    real(c_double), intent(in) :: z
+    real(c_double), intent(in), optional :: meshSize
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelGeoAddPoint = C_API(x=real(x, c_double), &
+                           y=real(y, c_double), &
+                           z=real(z, c_double), &
+                           meshSize=optval_c_double(0., meshSize), &
+                           tag=optval_c_int(-1, tag), &
+                           ierr_=ierr)
+    ! Post processing
+  end function gmshModelGeoAddPoint
+
+  !> Add a straight line segment in the built-in CAD representation, between the
+  !! two points with tags `startTag' and `endTag'. If `tag' is positive, set the
+  !! tag explicitly; otherwise a new tag is selected automatically. Return the
+  !! tag of the line.
+  function gmshModelGeoAddLine(startTag, &
+                               endTag, &
+                               tag, &
+                               ierr)
+    interface
+    function C_API(startTag, &
+                   endTag, &
+                   tag, &
+                   ierr_) &
+      bind(C, name="gmshModelGeoAddLine")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), value, intent(in) :: startTag
+      integer(c_int), value, intent(in) :: endTag
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelGeoAddLine
+    integer, intent(in) :: startTag
+    integer, intent(in) :: endTag
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelGeoAddLine = C_API(startTag=int(startTag, c_int), &
+                          endTag=int(endTag, c_int), &
+                          tag=optval_c_int(-1, tag), &
+                          ierr_=ierr)
+    ! Post processing
+  end function gmshModelGeoAddLine
+
+  !> Add a circle arc (strictly smaller than Pi) in the built-in CAD
+  !! representation, between the two points with tags `startTag' and `endTag',
+  !! and with center `centerTag'. If `tag' is positive, set the tag explicitly;
+  !! otherwise a new tag is selected automatically. If (`nx', `ny', `nz') != (0,
+  !! 0, 0), explicitly set the plane of the circle arc. Return the tag of the
+  !! circle arc.
+  function gmshModelGeoAddCircleArc(startTag, &
+                                    centerTag, &
+                                    endTag, &
+                                    tag, &
+                                    nx, &
+                                    ny, &
+                                    nz, &
+                                    ierr)
+    interface
+    function C_API(startTag, &
+                   centerTag, &
+                   endTag, &
+                   tag, &
+                   nx, &
+                   ny, &
+                   nz, &
+                   ierr_) &
+      bind(C, name="gmshModelGeoAddCircleArc")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), value, intent(in) :: startTag
+      integer(c_int), value, intent(in) :: centerTag
+      integer(c_int), value, intent(in) :: endTag
+      integer(c_int), value, intent(in) :: tag
+      real(c_double), value, intent(in) :: nx
+      real(c_double), value, intent(in) :: ny
+      real(c_double), value, intent(in) :: nz
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelGeoAddCircleArc
+    integer, intent(in) :: startTag
+    integer, intent(in) :: centerTag
+    integer, intent(in) :: endTag
+    integer, intent(in), optional :: tag
+    real(c_double), intent(in), optional :: nx
+    real(c_double), intent(in), optional :: ny
+    real(c_double), intent(in), optional :: nz
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelGeoAddCircleArc = C_API(startTag=int(startTag, c_int), &
+                               centerTag=int(centerTag, c_int), &
+                               endTag=int(endTag, c_int), &
+                               tag=optval_c_int(-1, tag), &
+                               nx=optval_c_double(0., nx), &
+                               ny=optval_c_double(0., ny), &
+                               nz=optval_c_double(0., nz), &
+                               ierr_=ierr)
+    ! Post processing
+  end function gmshModelGeoAddCircleArc
+
+  !> Add an ellipse arc (strictly smaller than Pi) in the built-in CAD
+  !! representation, between the two points `startTag' and `endTag', and with
+  !! center `centerTag' and major axis point `majorTag'. If `tag' is positive,
+  !! set the tag explicitly; otherwise a new tag is selected automatically. If
+  !! (`nx', `ny', `nz') != (0, 0, 0), explicitly set the plane of the circle
+  !! arc. Return the tag of the ellipse arc.
+  function gmshModelGeoAddEllipseArc(startTag, &
+                                     centerTag, &
+                                     majorTag, &
+                                     endTag, &
+                                     tag, &
+                                     nx, &
+                                     ny, &
+                                     nz, &
+                                     ierr)
+    interface
+    function C_API(startTag, &
+                   centerTag, &
+                   majorTag, &
+                   endTag, &
+                   tag, &
+                   nx, &
+                   ny, &
+                   nz, &
+                   ierr_) &
+      bind(C, name="gmshModelGeoAddEllipseArc")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), value, intent(in) :: startTag
+      integer(c_int), value, intent(in) :: centerTag
+      integer(c_int), value, intent(in) :: majorTag
+      integer(c_int), value, intent(in) :: endTag
+      integer(c_int), value, intent(in) :: tag
+      real(c_double), value, intent(in) :: nx
+      real(c_double), value, intent(in) :: ny
+      real(c_double), value, intent(in) :: nz
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelGeoAddEllipseArc
+    integer, intent(in) :: startTag
+    integer, intent(in) :: centerTag
+    integer, intent(in) :: majorTag
+    integer, intent(in) :: endTag
+    integer, intent(in), optional :: tag
+    real(c_double), intent(in), optional :: nx
+    real(c_double), intent(in), optional :: ny
+    real(c_double), intent(in), optional :: nz
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelGeoAddEllipseArc = C_API(startTag=int(startTag, c_int), &
+                                centerTag=int(centerTag, c_int), &
+                                majorTag=int(majorTag, c_int), &
+                                endTag=int(endTag, c_int), &
+                                tag=optval_c_int(-1, tag), &
+                                nx=optval_c_double(0., nx), &
+                                ny=optval_c_double(0., ny), &
+                                nz=optval_c_double(0., nz), &
+                                ierr_=ierr)
+    ! Post processing
+  end function gmshModelGeoAddEllipseArc
+
+  !> Add a spline (Catmull-Rom) curve in the built-in CAD representation, going
+  !! through the points `pointTags'. If `tag' is positive, set the tag
+  !! explicitly; otherwise a new tag is selected automatically. Create a
+  !! periodic curve if the first and last points are the same. Return the tag of
+  !! the spline curve.
+  function gmshModelGeoAddSpline(pointTags, &
+                                 tag, &
+                                 ierr)
+    interface
+    function C_API(api_pointTags_, &
+                   api_pointTags_n_, &
+                   tag, &
+                   ierr_) &
+      bind(C, name="gmshModelGeoAddSpline")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), dimension(*) :: api_pointTags_
+      integer(c_size_t), value, intent(in) :: api_pointTags_n_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelGeoAddSpline
+    integer(c_int), dimension(:), intent(in) :: pointTags
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelGeoAddSpline = C_API(api_pointTags_=pointTags, &
+                            api_pointTags_n_=size_gmsh_int(pointTags), &
+                            tag=optval_c_int(-1, tag), &
+                            ierr_=ierr)
+    ! Post processing
+  end function gmshModelGeoAddSpline
+
+  !> Add a cubic b-spline curve in the built-in CAD representation, with
+  !! `pointTags' control points. If `tag' is positive, set the tag explicitly;
+  !! otherwise a new tag is selected automatically. Creates a periodic curve if
+  !! the first and last points are the same. Return the tag of the b-spline
+  !! curve.
+  function gmshModelGeoAddBSpline(pointTags, &
+                                  tag, &
+                                  ierr)
+    interface
+    function C_API(api_pointTags_, &
+                   api_pointTags_n_, &
+                   tag, &
+                   ierr_) &
+      bind(C, name="gmshModelGeoAddBSpline")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), dimension(*) :: api_pointTags_
+      integer(c_size_t), value, intent(in) :: api_pointTags_n_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelGeoAddBSpline
+    integer(c_int), dimension(:), intent(in) :: pointTags
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelGeoAddBSpline = C_API(api_pointTags_=pointTags, &
+                             api_pointTags_n_=size_gmsh_int(pointTags), &
+                             tag=optval_c_int(-1, tag), &
+                             ierr_=ierr)
+    ! Post processing
+  end function gmshModelGeoAddBSpline
+
+  !> Add a Bezier curve in the built-in CAD representation, with `pointTags'
+  !! control points. If `tag' is positive, set the tag explicitly; otherwise a
+  !! new tag is selected automatically.  Return the tag of the Bezier curve.
+  function gmshModelGeoAddBezier(pointTags, &
+                                 tag, &
+                                 ierr)
+    interface
+    function C_API(api_pointTags_, &
+                   api_pointTags_n_, &
+                   tag, &
+                   ierr_) &
+      bind(C, name="gmshModelGeoAddBezier")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), dimension(*) :: api_pointTags_
+      integer(c_size_t), value, intent(in) :: api_pointTags_n_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelGeoAddBezier
+    integer(c_int), dimension(:), intent(in) :: pointTags
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelGeoAddBezier = C_API(api_pointTags_=pointTags, &
+                            api_pointTags_n_=size_gmsh_int(pointTags), &
+                            tag=optval_c_int(-1, tag), &
+                            ierr_=ierr)
+    ! Post processing
+  end function gmshModelGeoAddBezier
+
+  !> Add a polyline curve in the built-in CAD representation, going through the
+  !! points `pointTags'. If `tag' is positive, set the tag explicitly; otherwise
+  !! a new tag is selected automatically. Create a periodic curve if the first
+  !! and last points are the same. Return the tag of the polyline curve.
+  function gmshModelGeoAddPolyline(pointTags, &
+                                   tag, &
+                                   ierr)
+    interface
+    function C_API(api_pointTags_, &
+                   api_pointTags_n_, &
+                   tag, &
+                   ierr_) &
+      bind(C, name="gmshModelGeoAddPolyline")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), dimension(*) :: api_pointTags_
+      integer(c_size_t), value, intent(in) :: api_pointTags_n_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelGeoAddPolyline
+    integer(c_int), dimension(:), intent(in) :: pointTags
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelGeoAddPolyline = C_API(api_pointTags_=pointTags, &
+                              api_pointTags_n_=size_gmsh_int(pointTags), &
+                              tag=optval_c_int(-1, tag), &
+                              ierr_=ierr)
+    ! Post processing
+  end function gmshModelGeoAddPolyline
+
+  !> Add a spline (Catmull-Rom) curve in the built-in CAD representation, going
+  !! through points sampling the curves in `curveTags'. The density of sampling
+  !! points on each curve is governed by `numIntervals'. If `tag' is positive,
+  !! set the tag explicitly; otherwise a new tag is selected automatically.
+  !! Return the tag of the spline.
+  function gmshModelGeoAddCompoundSpline(curveTags, &
+                                         numIntervals, &
+                                         tag, &
+                                         ierr)
+    interface
+    function C_API(api_curveTags_, &
+                   api_curveTags_n_, &
+                   numIntervals, &
+                   tag, &
+                   ierr_) &
+      bind(C, name="gmshModelGeoAddCompoundSpline")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), dimension(*) :: api_curveTags_
+      integer(c_size_t), value, intent(in) :: api_curveTags_n_
+      integer(c_int), value, intent(in) :: numIntervals
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelGeoAddCompoundSpline
+    integer(c_int), dimension(:), intent(in) :: curveTags
+    integer, intent(in), optional :: numIntervals
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelGeoAddCompoundSpline = C_API(api_curveTags_=curveTags, &
+                                    api_curveTags_n_=size_gmsh_int(curveTags), &
+                                    numIntervals=optval_c_int(5, numIntervals), &
+                                    tag=optval_c_int(-1, tag), &
+                                    ierr_=ierr)
+    ! Post processing
+  end function gmshModelGeoAddCompoundSpline
+
+  !> Add a b-spline curve in the built-in CAD representation, with control
+  !! points sampling the curves in `curveTags'. The density of sampling points
+  !! on each curve is governed by `numIntervals'. If `tag' is positive, set the
+  !! tag explicitly; otherwise a new tag is selected automatically. Return the
+  !! tag of the b-spline.
+  function gmshModelGeoAddCompoundBSpline(curveTags, &
+                                          numIntervals, &
+                                          tag, &
+                                          ierr)
+    interface
+    function C_API(api_curveTags_, &
+                   api_curveTags_n_, &
+                   numIntervals, &
+                   tag, &
+                   ierr_) &
+      bind(C, name="gmshModelGeoAddCompoundBSpline")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), dimension(*) :: api_curveTags_
+      integer(c_size_t), value, intent(in) :: api_curveTags_n_
+      integer(c_int), value, intent(in) :: numIntervals
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelGeoAddCompoundBSpline
+    integer(c_int), dimension(:), intent(in) :: curveTags
+    integer, intent(in), optional :: numIntervals
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelGeoAddCompoundBSpline = C_API(api_curveTags_=curveTags, &
+                                     api_curveTags_n_=size_gmsh_int(curveTags), &
+                                     numIntervals=optval_c_int(20, numIntervals), &
+                                     tag=optval_c_int(-1, tag), &
+                                     ierr_=ierr)
+    ! Post processing
+  end function gmshModelGeoAddCompoundBSpline
+
+  !> Add a curve loop (a closed wire) in the built-in CAD representation, formed
+  !! by the curves `curveTags'. `curveTags' should contain (signed) tags of
+  !! model entities of dimension 1 forming a closed loop: a negative tag
+  !! signifies that the underlying curve is considered with reversed
+  !! orientation. If `tag' is positive, set the tag explicitly; otherwise a new
+  !! tag is selected automatically. If `reorient' is set, automatically reorient
+  !! the curves if necessary. Return the tag of the curve loop.
+  function gmshModelGeoAddCurveLoop(curveTags, &
+                                    tag, &
+                                    reorient, &
+                                    ierr)
+    interface
+    function C_API(api_curveTags_, &
+                   api_curveTags_n_, &
+                   tag, &
+                   reorient, &
+                   ierr_) &
+      bind(C, name="gmshModelGeoAddCurveLoop")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), dimension(*) :: api_curveTags_
+      integer(c_size_t), value, intent(in) :: api_curveTags_n_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: reorient
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelGeoAddCurveLoop
+    integer(c_int), dimension(:), intent(in) :: curveTags
+    integer, intent(in), optional :: tag
+    logical, intent(in), optional :: reorient
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelGeoAddCurveLoop = C_API(api_curveTags_=curveTags, &
+                               api_curveTags_n_=size_gmsh_int(curveTags), &
+                               tag=optval_c_int(-1, tag), &
+                               reorient=optval_c_bool(.false., reorient), &
+                               ierr_=ierr)
+    ! Post processing
+  end function gmshModelGeoAddCurveLoop
+
+  !> Add curve loops in the built-in CAD representation based on the curves
+  !! `curveTags'. Return the `tags' of found curve loops, if any.
+  subroutine gmshModelGeoAddCurveLoops(curveTags, &
+                                       tags, &
+                                       ierr)
+    interface
+    subroutine C_API(api_curveTags_, &
+                     api_curveTags_n_, &
+                     api_tags_, &
+                     api_tags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelGeoAddCurveLoops")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_curveTags_
+      integer(c_size_t), value, intent(in) :: api_curveTags_n_
+      type(c_ptr), intent(out) :: api_tags_
+      integer(c_size_t), intent(out) :: api_tags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:), intent(in) :: curveTags
+    integer(c_int), dimension(:), allocatable, intent(out) :: tags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_tags_
+    integer(c_size_t) :: api_tags_n_
+    call C_API(api_curveTags_=curveTags, &
+         api_curveTags_n_=size_gmsh_int(curveTags), &
+         api_tags_=api_tags_, &
+         api_tags_n_=api_tags_n_, &
+         ierr_=ierr)
+    ! Post processing
+    tags = ovectorint_(api_tags_, &
+      api_tags_n_)
+  end subroutine gmshModelGeoAddCurveLoops
+
+  !> Add a plane surface in the built-in CAD representation, defined by one or
+  !! more curve loops `wireTags'. The first curve loop defines the exterior
+  !! contour; additional curve loop define holes. If `tag' is positive, set the
+  !! tag explicitly; otherwise a new tag is selected automatically. Return the
+  !! tag of the surface.
+  function gmshModelGeoAddPlaneSurface(wireTags, &
+                                       tag, &
+                                       ierr)
+    interface
+    function C_API(api_wireTags_, &
+                   api_wireTags_n_, &
+                   tag, &
+                   ierr_) &
+      bind(C, name="gmshModelGeoAddPlaneSurface")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), dimension(*) :: api_wireTags_
+      integer(c_size_t), value, intent(in) :: api_wireTags_n_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelGeoAddPlaneSurface
+    integer(c_int), dimension(:), intent(in) :: wireTags
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelGeoAddPlaneSurface = C_API(api_wireTags_=wireTags, &
+                                  api_wireTags_n_=size_gmsh_int(wireTags), &
+                                  tag=optval_c_int(-1, tag), &
+                                  ierr_=ierr)
+    ! Post processing
+  end function gmshModelGeoAddPlaneSurface
+
+  !> Add a surface in the built-in CAD representation, filling the curve loops
+  !! in `wireTags' using transfinite interpolation. Currently only a single
+  !! curve loop is supported; this curve loop should be composed by 3 or 4
+  !! curves only. If `tag' is positive, set the tag explicitly; otherwise a new
+  !! tag is selected automatically. Return the tag of the surface.
+  function gmshModelGeoAddSurfaceFilling(wireTags, &
+                                         tag, &
+                                         sphereCenterTag, &
+                                         ierr)
+    interface
+    function C_API(api_wireTags_, &
+                   api_wireTags_n_, &
+                   tag, &
+                   sphereCenterTag, &
+                   ierr_) &
+      bind(C, name="gmshModelGeoAddSurfaceFilling")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), dimension(*) :: api_wireTags_
+      integer(c_size_t), value, intent(in) :: api_wireTags_n_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: sphereCenterTag
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelGeoAddSurfaceFilling
+    integer(c_int), dimension(:), intent(in) :: wireTags
+    integer, intent(in), optional :: tag
+    integer, intent(in), optional :: sphereCenterTag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelGeoAddSurfaceFilling = C_API(api_wireTags_=wireTags, &
+                                    api_wireTags_n_=size_gmsh_int(wireTags), &
+                                    tag=optval_c_int(-1, tag), &
+                                    sphereCenterTag=optval_c_int(-1, sphereCenterTag), &
+                                    ierr_=ierr)
+    ! Post processing
+  end function gmshModelGeoAddSurfaceFilling
+
+  !> Add a surface loop (a closed shell) formed by `surfaceTags' in the built-in
+  !! CAD representation.  If `tag' is positive, set the tag explicitly;
+  !! otherwise a new tag is selected automatically. Return the tag of the shell.
+  function gmshModelGeoAddSurfaceLoop(surfaceTags, &
+                                      tag, &
+                                      ierr)
+    interface
+    function C_API(api_surfaceTags_, &
+                   api_surfaceTags_n_, &
+                   tag, &
+                   ierr_) &
+      bind(C, name="gmshModelGeoAddSurfaceLoop")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), dimension(*) :: api_surfaceTags_
+      integer(c_size_t), value, intent(in) :: api_surfaceTags_n_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelGeoAddSurfaceLoop
+    integer(c_int), dimension(:), intent(in) :: surfaceTags
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelGeoAddSurfaceLoop = C_API(api_surfaceTags_=surfaceTags, &
+                                 api_surfaceTags_n_=size_gmsh_int(surfaceTags), &
+                                 tag=optval_c_int(-1, tag), &
+                                 ierr_=ierr)
+    ! Post processing
+  end function gmshModelGeoAddSurfaceLoop
+
+  !> Add a volume (a region) in the built-in CAD representation, defined by one
+  !! or more shells `shellTags'. The first surface loop defines the exterior
+  !! boundary; additional surface loop define holes. If `tag' is positive, set
+  !! the tag explicitly; otherwise a new tag is selected automatically. Return
+  !! the tag of the volume.
+  function gmshModelGeoAddVolume(shellTags, &
+                                 tag, &
+                                 ierr)
+    interface
+    function C_API(api_shellTags_, &
+                   api_shellTags_n_, &
+                   tag, &
+                   ierr_) &
+      bind(C, name="gmshModelGeoAddVolume")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), dimension(*) :: api_shellTags_
+      integer(c_size_t), value, intent(in) :: api_shellTags_n_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelGeoAddVolume
+    integer(c_int), dimension(:), intent(in) :: shellTags
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelGeoAddVolume = C_API(api_shellTags_=shellTags, &
+                            api_shellTags_n_=size_gmsh_int(shellTags), &
+                            tag=optval_c_int(-1, tag), &
+                            ierr_=ierr)
+    ! Post processing
+  end function gmshModelGeoAddVolume
+
+  !> Add a `geometry' in the built-in CAD representation. `geometry' can
+  !! currently be one of "Sphere" or "PolarSphere" (where `numbers' should
+  !! contain the x, y, z coordinates of the center, followed by the radius), or
+  !! "Parametric" (where `strings' should contains three expression evaluating
+  !! to the x, y and z coordinates. If `tag' is positive, set the tag of the
+  !! geometry explicitly; otherwise a new tag is selected automatically. Return
+  !! the tag of the geometry.
+  function gmshModelGeoAddGeometry(geometry, &
+                                   numbers, &
+                                   strings, &
+                                   tag, &
+                                   ierr)
+    interface
+    function C_API(geometry, &
+                   api_numbers_, &
+                   api_numbers_n_, &
+                   api_strings_, &
+                   api_strings_n_, &
+                   tag, &
+                   ierr_) &
+      bind(C, name="gmshModelGeoAddGeometry")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      character(len=1, kind=c_char), dimension(*), intent(in) :: geometry
+      real(c_double), dimension(*), optional :: api_numbers_
+      integer(c_size_t), value, intent(in) :: api_numbers_n_
+      type(c_ptr), dimension(*), optional :: api_strings_
+      integer(c_size_t), value, intent(in) :: api_strings_n_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelGeoAddGeometry
+    character(len=*), intent(in) :: geometry
+    real(c_double), dimension(:), intent(in), optional :: numbers
+    character(len=*), dimension(:), intent(in), optional :: strings
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    character(len=GMSH_API_MAX_STR_LEN, kind=c_char), allocatable :: api_strings_strs(:)
+    type(c_ptr), allocatable :: api_strings_(:)
+    call ivectorstring_(strings, &
+      api_strings_strs, &
+      api_strings_)
+    gmshModelGeoAddGeometry = C_API(geometry=istring_(geometry), &
+                              api_numbers_=numbers, &
+                              api_numbers_n_=size_gmsh_double(numbers), &
+                              api_strings_=api_strings_, &
+                              api_strings_n_=size_gmsh_str(strings), &
+                              tag=optval_c_int(-1, tag), &
+                              ierr_=ierr)
+    ! Post processing
+  end function gmshModelGeoAddGeometry
+
+  !> Add a point in the built-in CAD representation, at coordinates (`x', `y',
+  !! `z') on the geometry `geometryTag'. If `meshSize' is > 0, add a meshing
+  !! constraint at that point. If `tag' is positive, set the tag explicitly;
+  !! otherwise a new tag is selected automatically. Return the tag of the point.
+  !! For surface geometries, only the `x' and `y' coordinates are used.
+  function gmshModelGeoAddPointOnGeometry(geometryTag, &
+                                          x, &
+                                          y, &
+                                          z, &
+                                          meshSize, &
+                                          tag, &
+                                          ierr)
+    interface
+    function C_API(geometryTag, &
+                   x, &
+                   y, &
+                   z, &
+                   meshSize, &
+                   tag, &
+                   ierr_) &
+      bind(C, name="gmshModelGeoAddPointOnGeometry")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), value, intent(in) :: geometryTag
+      real(c_double), value, intent(in) :: x
+      real(c_double), value, intent(in) :: y
+      real(c_double), value, intent(in) :: z
+      real(c_double), value, intent(in) :: meshSize
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelGeoAddPointOnGeometry
+    integer, intent(in) :: geometryTag
+    real(c_double), intent(in) :: x
+    real(c_double), intent(in) :: y
+    real(c_double), intent(in), optional :: z
+    real(c_double), intent(in), optional :: meshSize
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelGeoAddPointOnGeometry = C_API(geometryTag=int(geometryTag, c_int), &
+                                     x=real(x, c_double), &
+                                     y=real(y, c_double), &
+                                     z=optval_c_double(0., z), &
+                                     meshSize=optval_c_double(0., meshSize), &
+                                     tag=optval_c_int(-1, tag), &
+                                     ierr_=ierr)
+    ! Post processing
+  end function gmshModelGeoAddPointOnGeometry
+
+  !> Extrude the entities `dimTags' in the built-in CAD representation, using a
+  !! translation along (`dx', `dy', `dz'). Return 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 (cumulative) height of the different
+  !! layers, normalized to 1. If `recombine' is set, recombine the mesh in the
+  !! layers.
+  subroutine gmshModelGeoExtrude(dimTags, &
+                                 dx, &
+                                 dy, &
+                                 dz, &
+                                 outDimTags, &
+                                 numElements, &
+                                 heights, &
+                                 recombine, &
+                                 ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     dx, &
+                     dy, &
+                     dz, &
+                     api_outDimTags_, &
+                     api_outDimTags_n_, &
+                     api_numElements_, &
+                     api_numElements_n_, &
+                     api_heights_, &
+                     api_heights_n_, &
+                     recombine, &
+                     ierr_) &
+      bind(C, name="gmshModelGeoExtrude")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      real(c_double), value, intent(in) :: dx
+      real(c_double), value, intent(in) :: dy
+      real(c_double), value, intent(in) :: dz
+      type(c_ptr), intent(out) :: api_outDimTags_
+      integer(c_size_t), intent(out) :: api_outDimTags_n_
+      integer(c_int), dimension(*), optional :: api_numElements_
+      integer(c_size_t), value, intent(in) :: api_numElements_n_
+      real(c_double), dimension(*), optional :: api_heights_
+      integer(c_size_t), value, intent(in) :: api_heights_n_
+      integer(c_int), value, intent(in) :: recombine
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    real(c_double), intent(in) :: dx
+    real(c_double), intent(in) :: dy
+    real(c_double), intent(in) :: dz
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: outDimTags
+    integer(c_int), dimension(:), intent(in), optional :: numElements
+    real(c_double), dimension(:), intent(in), optional :: heights
+    logical, intent(in), optional :: recombine
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_outDimTags_
+    integer(c_size_t) :: api_outDimTags_n_
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         dx=real(dx, c_double), &
+         dy=real(dy, c_double), &
+         dz=real(dz, c_double), &
+         api_outDimTags_=api_outDimTags_, &
+         api_outDimTags_n_=api_outDimTags_n_, &
+         api_numElements_=numElements, &
+         api_numElements_n_=size_gmsh_int(numElements), &
+         api_heights_=heights, &
+         api_heights_n_=size_gmsh_double(heights), &
+         recombine=optval_c_bool(.false., recombine), &
+         ierr_=ierr)
+    ! Post processing
+    outDimTags = ovectorpair_(api_outDimTags_, &
+      api_outDimTags_n_)
+  end subroutine gmshModelGeoExtrude
+
+  !> Extrude the entities `dimTags' in the built-in CAD representation, using a
+  !! rotation of `angle' radians around the axis of revolution defined by the
+  !! point (`x', `y', `z') and the direction (`ax', `ay', `az'). The angle
+  !! should be strictly smaller than Pi. Return 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 (cumulative) height of the different
+  !! layers, normalized to 1. If `recombine' is set, recombine the mesh in the
+  !! layers.
+  subroutine gmshModelGeoRevolve(dimTags, &
+                                 x, &
+                                 y, &
+                                 z, &
+                                 ax, &
+                                 ay, &
+                                 az, &
+                                 angle, &
+                                 outDimTags, &
+                                 numElements, &
+                                 heights, &
+                                 recombine, &
+                                 ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     x, &
+                     y, &
+                     z, &
+                     ax, &
+                     ay, &
+                     az, &
+                     angle, &
+                     api_outDimTags_, &
+                     api_outDimTags_n_, &
+                     api_numElements_, &
+                     api_numElements_n_, &
+                     api_heights_, &
+                     api_heights_n_, &
+                     recombine, &
+                     ierr_) &
+      bind(C, name="gmshModelGeoRevolve")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      real(c_double), value, intent(in) :: x
+      real(c_double), value, intent(in) :: y
+      real(c_double), value, intent(in) :: z
+      real(c_double), value, intent(in) :: ax
+      real(c_double), value, intent(in) :: ay
+      real(c_double), value, intent(in) :: az
+      real(c_double), value, intent(in) :: angle
+      type(c_ptr), intent(out) :: api_outDimTags_
+      integer(c_size_t), intent(out) :: api_outDimTags_n_
+      integer(c_int), dimension(*), optional :: api_numElements_
+      integer(c_size_t), value, intent(in) :: api_numElements_n_
+      real(c_double), dimension(*), optional :: api_heights_
+      integer(c_size_t), value, intent(in) :: api_heights_n_
+      integer(c_int), value, intent(in) :: recombine
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    real(c_double), intent(in) :: x
+    real(c_double), intent(in) :: y
+    real(c_double), intent(in) :: z
+    real(c_double), intent(in) :: ax
+    real(c_double), intent(in) :: ay
+    real(c_double), intent(in) :: az
+    real(c_double), intent(in) :: angle
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: outDimTags
+    integer(c_int), dimension(:), intent(in), optional :: numElements
+    real(c_double), dimension(:), intent(in), optional :: heights
+    logical, intent(in), optional :: recombine
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_outDimTags_
+    integer(c_size_t) :: api_outDimTags_n_
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         x=real(x, c_double), &
+         y=real(y, c_double), &
+         z=real(z, c_double), &
+         ax=real(ax, c_double), &
+         ay=real(ay, c_double), &
+         az=real(az, c_double), &
+         angle=real(angle, c_double), &
+         api_outDimTags_=api_outDimTags_, &
+         api_outDimTags_n_=api_outDimTags_n_, &
+         api_numElements_=numElements, &
+         api_numElements_n_=size_gmsh_int(numElements), &
+         api_heights_=heights, &
+         api_heights_n_=size_gmsh_double(heights), &
+         recombine=optval_c_bool(.false., recombine), &
+         ierr_=ierr)
+    ! Post processing
+    outDimTags = ovectorpair_(api_outDimTags_, &
+      api_outDimTags_n_)
+  end subroutine gmshModelGeoRevolve
+
+  !> Extrude the entities `dimTags' in the built-in CAD representation, using 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'). The angle should be strictly
+  !! smaller than Pi. Return 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
+  !! (cumulative) height of the different layers, normalized to 1. If
+  !! `recombine' is set, recombine the mesh in the layers.
+  subroutine gmshModelGeoTwist(dimTags, &
+                               x, &
+                               y, &
+                               z, &
+                               dx, &
+                               dy, &
+                               dz, &
+                               ax, &
+                               ay, &
+                               az, &
+                               angle, &
+                               outDimTags, &
+                               numElements, &
+                               heights, &
+                               recombine, &
+                               ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     x, &
+                     y, &
+                     z, &
+                     dx, &
+                     dy, &
+                     dz, &
+                     ax, &
+                     ay, &
+                     az, &
+                     angle, &
+                     api_outDimTags_, &
+                     api_outDimTags_n_, &
+                     api_numElements_, &
+                     api_numElements_n_, &
+                     api_heights_, &
+                     api_heights_n_, &
+                     recombine, &
+                     ierr_) &
+      bind(C, name="gmshModelGeoTwist")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      real(c_double), value, intent(in) :: x
+      real(c_double), value, intent(in) :: y
+      real(c_double), value, intent(in) :: z
+      real(c_double), value, intent(in) :: dx
+      real(c_double), value, intent(in) :: dy
+      real(c_double), value, intent(in) :: dz
+      real(c_double), value, intent(in) :: ax
+      real(c_double), value, intent(in) :: ay
+      real(c_double), value, intent(in) :: az
+      real(c_double), value, intent(in) :: angle
+      type(c_ptr), intent(out) :: api_outDimTags_
+      integer(c_size_t), intent(out) :: api_outDimTags_n_
+      integer(c_int), dimension(*), optional :: api_numElements_
+      integer(c_size_t), value, intent(in) :: api_numElements_n_
+      real(c_double), dimension(*), optional :: api_heights_
+      integer(c_size_t), value, intent(in) :: api_heights_n_
+      integer(c_int), value, intent(in) :: recombine
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    real(c_double), intent(in) :: x
+    real(c_double), intent(in) :: y
+    real(c_double), intent(in) :: z
+    real(c_double), intent(in) :: dx
+    real(c_double), intent(in) :: dy
+    real(c_double), intent(in) :: dz
+    real(c_double), intent(in) :: ax
+    real(c_double), intent(in) :: ay
+    real(c_double), intent(in) :: az
+    real(c_double), intent(in) :: angle
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: outDimTags
+    integer(c_int), dimension(:), intent(in), optional :: numElements
+    real(c_double), dimension(:), intent(in), optional :: heights
+    logical, intent(in), optional :: recombine
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_outDimTags_
+    integer(c_size_t) :: api_outDimTags_n_
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         x=real(x, c_double), &
+         y=real(y, c_double), &
+         z=real(z, c_double), &
+         dx=real(dx, c_double), &
+         dy=real(dy, c_double), &
+         dz=real(dz, c_double), &
+         ax=real(ax, c_double), &
+         ay=real(ay, c_double), &
+         az=real(az, c_double), &
+         angle=real(angle, c_double), &
+         api_outDimTags_=api_outDimTags_, &
+         api_outDimTags_n_=api_outDimTags_n_, &
+         api_numElements_=numElements, &
+         api_numElements_n_=size_gmsh_int(numElements), &
+         api_heights_=heights, &
+         api_heights_n_=size_gmsh_double(heights), &
+         recombine=optval_c_bool(.false., recombine), &
+         ierr_=ierr)
+    ! Post processing
+    outDimTags = ovectorpair_(api_outDimTags_, &
+      api_outDimTags_n_)
+  end subroutine gmshModelGeoTwist
+
+  !> Extrude the entities `dimTags' in the built-in CAD representation along the
+  !! normals of the mesh, creating discrete boundary layer entities. Return
+  !! extruded entities in `outDimTags'. The entries in `numElements' give the
+  !! number of elements in each layer. If `height' is not empty, it provides the
+  !! (cumulative) height of the different layers. If `recombine' is set,
+  !! recombine the mesh in the layers. A second boundary layer can be created
+  !! from the same entities if `second' is set. If `viewIndex' is >= 0, use the
+  !! corresponding view to either specify the normals (if the view contains a
+  !! vector field) or scale the normals (if the view is scalar).
+  subroutine gmshModelGeoExtrudeBoundaryLayer(dimTags, &
+                                              outDimTags, &
+                                              numElements, &
+                                              heights, &
+                                              recombine, &
+                                              second, &
+                                              viewIndex, &
+                                              ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     api_outDimTags_, &
+                     api_outDimTags_n_, &
+                     api_numElements_, &
+                     api_numElements_n_, &
+                     api_heights_, &
+                     api_heights_n_, &
+                     recombine, &
+                     second, &
+                     viewIndex, &
+                     ierr_) &
+      bind(C, name="gmshModelGeoExtrudeBoundaryLayer")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      type(c_ptr), intent(out) :: api_outDimTags_
+      integer(c_size_t), intent(out) :: api_outDimTags_n_
+      integer(c_int), dimension(*), optional :: api_numElements_
+      integer(c_size_t), value, intent(in) :: api_numElements_n_
+      real(c_double), dimension(*), optional :: api_heights_
+      integer(c_size_t), value, intent(in) :: api_heights_n_
+      integer(c_int), value, intent(in) :: recombine
+      integer(c_int), value, intent(in) :: second
+      integer(c_int), value, intent(in) :: viewIndex
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: outDimTags
+    integer(c_int), dimension(:), intent(in), optional :: numElements
+    real(c_double), dimension(:), intent(in), optional :: heights
+    logical, intent(in), optional :: recombine
+    logical, intent(in), optional :: second
+    integer, intent(in), optional :: viewIndex
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_outDimTags_
+    integer(c_size_t) :: api_outDimTags_n_
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         api_outDimTags_=api_outDimTags_, &
+         api_outDimTags_n_=api_outDimTags_n_, &
+         api_numElements_=numElements, &
+         api_numElements_n_=size_gmsh_int(numElements), &
+         api_heights_=heights, &
+         api_heights_n_=size_gmsh_double(heights), &
+         recombine=optval_c_bool(.false., recombine), &
+         second=optval_c_bool(.false., second), &
+         viewIndex=optval_c_int(-1, viewIndex), &
+         ierr_=ierr)
+    ! Post processing
+    outDimTags = ovectorpair_(api_outDimTags_, &
+      api_outDimTags_n_)
+  end subroutine gmshModelGeoExtrudeBoundaryLayer
+
+  !> Translate the entities `dimTags' in the built-in CAD representation along
+  !! (`dx', `dy', `dz').
+  subroutine gmshModelGeoTranslate(dimTags, &
+                                   dx, &
+                                   dy, &
+                                   dz, &
+                                   ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     dx, &
+                     dy, &
+                     dz, &
+                     ierr_) &
+      bind(C, name="gmshModelGeoTranslate")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      real(c_double), value, intent(in) :: dx
+      real(c_double), value, intent(in) :: dy
+      real(c_double), value, intent(in) :: dz
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    real(c_double), intent(in) :: dx
+    real(c_double), intent(in) :: dy
+    real(c_double), intent(in) :: dz
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         dx=real(dx, c_double), &
+         dy=real(dy, c_double), &
+         dz=real(dz, c_double), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelGeoTranslate
+
+  !> Rotate the entities `dimTags' in the built-in CAD representation by `angle'
+  !! radians around the axis of revolution defined by the point (`x', `y', `z')
+  !! and the direction (`ax', `ay', `az').
+  subroutine gmshModelGeoRotate(dimTags, &
+                                x, &
+                                y, &
+                                z, &
+                                ax, &
+                                ay, &
+                                az, &
+                                angle, &
+                                ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     x, &
+                     y, &
+                     z, &
+                     ax, &
+                     ay, &
+                     az, &
+                     angle, &
+                     ierr_) &
+      bind(C, name="gmshModelGeoRotate")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      real(c_double), value, intent(in) :: x
+      real(c_double), value, intent(in) :: y
+      real(c_double), value, intent(in) :: z
+      real(c_double), value, intent(in) :: ax
+      real(c_double), value, intent(in) :: ay
+      real(c_double), value, intent(in) :: az
+      real(c_double), value, intent(in) :: angle
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    real(c_double), intent(in) :: x
+    real(c_double), intent(in) :: y
+    real(c_double), intent(in) :: z
+    real(c_double), intent(in) :: ax
+    real(c_double), intent(in) :: ay
+    real(c_double), intent(in) :: az
+    real(c_double), intent(in) :: angle
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         x=real(x, c_double), &
+         y=real(y, c_double), &
+         z=real(z, c_double), &
+         ax=real(ax, c_double), &
+         ay=real(ay, c_double), &
+         az=real(az, c_double), &
+         angle=real(angle, c_double), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelGeoRotate
+
+  !> Scale the entities `dimTag' in the built-in CAD representation by factors
+  !! `a', `b' and `c' along the three coordinate axes; use (`x', `y', `z') as
+  !! the center of the homothetic transformation.
+  subroutine gmshModelGeoDilate(dimTags, &
+                                x, &
+                                y, &
+                                z, &
+                                a, &
+                                b, &
+                                c, &
+                                ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     x, &
+                     y, &
+                     z, &
+                     a, &
+                     b, &
+                     c, &
+                     ierr_) &
+      bind(C, name="gmshModelGeoDilate")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      real(c_double), value, intent(in) :: x
+      real(c_double), value, intent(in) :: y
+      real(c_double), value, intent(in) :: z
+      real(c_double), value, intent(in) :: a
+      real(c_double), value, intent(in) :: b
+      real(c_double), value, intent(in) :: c
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    real(c_double), intent(in) :: x
+    real(c_double), intent(in) :: y
+    real(c_double), intent(in) :: z
+    real(c_double), intent(in) :: a
+    real(c_double), intent(in) :: b
+    real(c_double), intent(in) :: c
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         x=real(x, c_double), &
+         y=real(y, c_double), &
+         z=real(z, c_double), &
+         a=real(a, c_double), &
+         b=real(b, c_double), &
+         c=real(c, c_double), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelGeoDilate
+
+  !> Mirror the entities `dimTag' in the built-in CAD representation, with
+  !! respect to the plane of equation `a' * x + `b' * y + `c' * z + `d' = 0.
+  subroutine gmshModelGeoMirror(dimTags, &
+                                a, &
+                                b, &
+                                c, &
+                                d, &
+                                ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     a, &
+                     b, &
+                     c, &
+                     d, &
+                     ierr_) &
+      bind(C, name="gmshModelGeoMirror")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      real(c_double), value, intent(in) :: a
+      real(c_double), value, intent(in) :: b
+      real(c_double), value, intent(in) :: c
+      real(c_double), value, intent(in) :: d
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    real(c_double), intent(in) :: a
+    real(c_double), intent(in) :: b
+    real(c_double), intent(in) :: c
+    real(c_double), intent(in) :: d
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         a=real(a, c_double), &
+         b=real(b, c_double), &
+         c=real(c, c_double), &
+         d=real(d, c_double), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelGeoMirror
+
+  !> Mirror the entities `dimTag' in the built-in CAD representation, with
+  !! respect to the plane of equation `a' * x + `b' * y + `c' * z + `d' = 0.
+  !! (This is a synonym for `mirror', which will be deprecated in a future
+  !! release.)
+  subroutine gmshModelGeoSymmetrize(dimTags, &
+                                    a, &
+                                    b, &
+                                    c, &
+                                    d, &
+                                    ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     a, &
+                     b, &
+                     c, &
+                     d, &
+                     ierr_) &
+      bind(C, name="gmshModelGeoSymmetrize")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      real(c_double), value, intent(in) :: a
+      real(c_double), value, intent(in) :: b
+      real(c_double), value, intent(in) :: c
+      real(c_double), value, intent(in) :: d
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    real(c_double), intent(in) :: a
+    real(c_double), intent(in) :: b
+    real(c_double), intent(in) :: c
+    real(c_double), intent(in) :: d
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         a=real(a, c_double), &
+         b=real(b, c_double), &
+         c=real(c, c_double), &
+         d=real(d, c_double), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelGeoSymmetrize
+
+  !> Copy the entities `dimTags' in the built-in CAD representation; the new
+  !! entities are returned in `outDimTags'.
+  subroutine gmshModelGeoCopy(dimTags, &
+                              outDimTags, &
+                              ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     api_outDimTags_, &
+                     api_outDimTags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelGeoCopy")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      type(c_ptr), intent(out) :: api_outDimTags_
+      integer(c_size_t), intent(out) :: api_outDimTags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: outDimTags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_outDimTags_
+    integer(c_size_t) :: api_outDimTags_n_
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         api_outDimTags_=api_outDimTags_, &
+         api_outDimTags_n_=api_outDimTags_n_, &
+         ierr_=ierr)
+    ! Post processing
+    outDimTags = ovectorpair_(api_outDimTags_, &
+      api_outDimTags_n_)
+  end subroutine gmshModelGeoCopy
+
+  !> Remove the entities `dimTags' in the built-in CAD representation, provided
+  !! that they are not on the boundary of higher-dimensional entities. If
+  !! `recursive' is true, remove all the entities on their boundaries, down to
+  !! dimension 0.
+  subroutine gmshModelGeoRemove(dimTags, &
+                                recursive, &
+                                ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     recursive, &
+                     ierr_) &
+      bind(C, name="gmshModelGeoRemove")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      integer(c_int), value, intent(in) :: recursive
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    logical, intent(in), optional :: recursive
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         recursive=optval_c_bool(.false., recursive), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelGeoRemove
+
+  !> Remove all duplicate entities in the built-in CAD representation (different
+  !! entities at the same geometrical location).
+  subroutine gmshModelGeoRemoveAllDuplicates(ierr)
+    interface
+    subroutine C_API(ierr_) &
+      bind(C, name="gmshModelGeoRemoveAllDuplicates")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelGeoRemoveAllDuplicates
+
+  !> Split the curve of tag `tag' in the built-in CAD representation, on the
+  !! specified control points `pointTags'. This feature is only available for
+  !! lines, splines and b-splines. Return the tag(s) `curveTags' of the newly
+  !! created curve(s).
+  subroutine gmshModelGeoSplitCurve(tag, &
+                                    pointTags, &
+                                    curveTags, &
+                                    ierr)
+    interface
+    subroutine C_API(tag, &
+                     api_pointTags_, &
+                     api_pointTags_n_, &
+                     api_curveTags_, &
+                     api_curveTags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelGeoSplitCurve")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), dimension(*) :: api_pointTags_
+      integer(c_size_t), value, intent(in) :: api_pointTags_n_
+      type(c_ptr), intent(out) :: api_curveTags_
+      integer(c_size_t), intent(out) :: api_curveTags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    integer(c_int), dimension(:), intent(in) :: pointTags
+    integer(c_int), dimension(:), allocatable, intent(out) :: curveTags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_curveTags_
+    integer(c_size_t) :: api_curveTags_n_
+    call C_API(tag=int(tag, c_int), &
+         api_pointTags_=pointTags, &
+         api_pointTags_n_=size_gmsh_int(pointTags), &
+         api_curveTags_=api_curveTags_, &
+         api_curveTags_n_=api_curveTags_n_, &
+         ierr_=ierr)
+    ! Post processing
+    curveTags = ovectorint_(api_curveTags_, &
+      api_curveTags_n_)
+  end subroutine gmshModelGeoSplitCurve
+
+  !> Get the maximum tag of entities of dimension `dim' in the built-in CAD
+  !! representation.
+  function gmshModelGeoGetMaxTag(dim, &
+                                 ierr)
+    interface
+    function C_API(dim, &
+                   ierr_) &
+      bind(C, name="gmshModelGeoGetMaxTag")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelGeoGetMaxTag
+    integer, intent(in) :: dim
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelGeoGetMaxTag = C_API(dim=int(dim, c_int), &
+                            ierr_=ierr)
+    ! Post processing
+  end function gmshModelGeoGetMaxTag
+
+  !> Set the maximum tag `maxTag' for entities of dimension `dim' in the built-
+  !! in CAD representation.
+  subroutine gmshModelGeoSetMaxTag(dim, &
+                                   maxTag, &
+                                   ierr)
+    interface
+    subroutine C_API(dim, &
+                     maxTag, &
+                     ierr_) &
+      bind(C, name="gmshModelGeoSetMaxTag")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: maxTag
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: maxTag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=int(dim, c_int), &
+         maxTag=int(maxTag, c_int), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelGeoSetMaxTag
+
+  !> Add a physical group of dimension `dim', grouping the entities with tags
+  !! `tags' in the built-in CAD representation. Return the tag of the physical
+  !! group, equal to `tag' if `tag' is positive, or a new tag if `tag' < 0. Set
+  !! the name of the physical group if `name' is not empty.
+  function gmshModelGeoAddPhysicalGroup(dim, &
+                                        tags, &
+                                        tag, &
+                                        name, &
+                                        ierr)
+    interface
+    function C_API(dim, &
+                   api_tags_, &
+                   api_tags_n_, &
+                   tag, &
+                   name, &
+                   ierr_) &
+      bind(C, name="gmshModelGeoAddPhysicalGroup")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), dimension(*) :: api_tags_
+      integer(c_size_t), value, intent(in) :: api_tags_n_
+      integer(c_int), value, intent(in) :: tag
+      character(len=1, kind=c_char), dimension(*), intent(in), optional :: name
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelGeoAddPhysicalGroup
+    integer, intent(in) :: dim
+    integer(c_int), dimension(:), intent(in) :: tags
+    integer, intent(in), optional :: tag
+    character(len=*), intent(in), optional :: name
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelGeoAddPhysicalGroup = C_API(dim=int(dim, c_int), &
+                                   api_tags_=tags, &
+                                   api_tags_n_=size_gmsh_int(tags), &
+                                   tag=optval_c_int(-1, tag), &
+                                   name=istring_(optval_c_str("", name)), &
+                                   ierr_=ierr)
+    ! Post processing
+  end function gmshModelGeoAddPhysicalGroup
+
+  !> Remove the physical groups `dimTags' from the built-in CAD representation.
+  !! If `dimTags' is empty, remove all groups.
+  subroutine gmshModelGeoRemovePhysicalGroups(dimTags, &
+                                              ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelGeoRemovePhysicalGroups")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*), optional :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in), optional :: dimTags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelGeoRemovePhysicalGroups
+
+  !> Synchronize the built-in 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. Without synchronization the entities in the built-in CAD
+  !! representation are not available to any function outside of the built-in
+  !! CAD kernel functions.
+  subroutine gmshModelGeoSynchronize(ierr)
+    interface
+    subroutine C_API(ierr_) &
+      bind(C, name="gmshModelGeoSynchronize")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelGeoSynchronize
+
+  !> Set a mesh size constraint on the entities `dimTags' in the built-in CAD
+  !! kernel representation. Currently only entities of dimension 0 (points) are
+  !! handled.
+  subroutine gmshModelGeoMeshSetSize(dimTags, &
+                                     size, &
+                                     ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     size, &
+                     ierr_) &
+      bind(C, name="gmshModelGeoMeshSetSize")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      real(c_double), value, intent(in) :: size
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    real(c_double), intent(in) :: size
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         size=real(size, c_double), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelGeoMeshSetSize
+
+  !> Set a transfinite meshing constraint on the curve `tag' in the built-in CAD
+  !! kernel representation, with `numNodes' nodes distributed according to
+  !! `meshType' and `coef'. Currently supported types are "Progression"
+  !! (geometrical progression with power `coef') and "Bump" (refinement toward
+  !! both extremities of the curve).
+  subroutine gmshModelGeoMeshSetTransfiniteCurve(tag, &
+                                                 nPoints, &
+                                                 meshType, &
+                                                 coef, &
+                                                 ierr)
+    interface
+    subroutine C_API(tag, &
+                     nPoints, &
+                     meshType, &
+                     coef, &
+                     ierr_) &
+      bind(C, name="gmshModelGeoMeshSetTransfiniteCurve")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: nPoints
+      character(len=1, kind=c_char), dimension(*), intent(in), optional :: meshType
+      real(c_double), value, intent(in) :: coef
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    integer, intent(in) :: nPoints
+    character(len=*), intent(in), optional :: meshType
+    real(c_double), intent(in), optional :: coef
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(tag=int(tag, c_int), &
+         nPoints=int(nPoints, c_int), &
+         meshType=istring_(optval_c_str("Progression", meshType)), &
+         coef=optval_c_double(1., coef), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelGeoMeshSetTransfiniteCurve
+
+  !> Set a transfinite meshing constraint on the surface `tag' in the built-in
+  !! CAD kernel representation. `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.
+  subroutine gmshModelGeoMeshSetTransfiniteSurface(tag, &
+                                                   arrangement, &
+                                                   cornerTags, &
+                                                   ierr)
+    interface
+    subroutine C_API(tag, &
+                     arrangement, &
+                     api_cornerTags_, &
+                     api_cornerTags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelGeoMeshSetTransfiniteSurface")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      character(len=1, kind=c_char), dimension(*), intent(in), optional :: arrangement
+      integer(c_int), dimension(*), optional :: api_cornerTags_
+      integer(c_size_t), value, intent(in) :: api_cornerTags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    character(len=*), intent(in), optional :: arrangement
+    integer(c_int), dimension(:), intent(in), optional :: cornerTags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(tag=int(tag, c_int), &
+         arrangement=istring_(optval_c_str("Left", arrangement)), &
+         api_cornerTags_=cornerTags, &
+         api_cornerTags_n_=size_gmsh_int(cornerTags), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelGeoMeshSetTransfiniteSurface
+
+  !> Set a transfinite meshing constraint on the surface `tag' in the built-in
+  !! CAD kernel representation. `cornerTags' can be used to specify the (6 or 8)
+  !! corners of the transfinite interpolation explicitly.
+  subroutine gmshModelGeoMeshSetTransfiniteVolume(tag, &
+                                                  cornerTags, &
+                                                  ierr)
+    interface
+    subroutine C_API(tag, &
+                     api_cornerTags_, &
+                     api_cornerTags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelGeoMeshSetTransfiniteVolume")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), dimension(*), optional :: api_cornerTags_
+      integer(c_size_t), value, intent(in) :: api_cornerTags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    integer(c_int), dimension(:), intent(in), optional :: cornerTags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(tag=int(tag, c_int), &
+         api_cornerTags_=cornerTags, &
+         api_cornerTags_n_=size_gmsh_int(cornerTags), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelGeoMeshSetTransfiniteVolume
+
+  !> Set a recombination meshing constraint on the entity of dimension `dim' and
+  !! tag `tag' in the built-in CAD kernel representation. Currently only
+  !! entities of dimension 2 (to recombine triangles into quadrangles) are
+  !! supported; `angle' specifies the threshold angle for the simple
+  !! recombination algorithm.
+  subroutine gmshModelGeoMeshSetRecombine(dim, &
+                                          tag, &
+                                          angle, &
+                                          ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     angle, &
+                     ierr_) &
+      bind(C, name="gmshModelGeoMeshSetRecombine")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      real(c_double), value, intent(in) :: angle
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    real(c_double), intent(in), optional :: angle
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         angle=optval_c_double(45., angle), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelGeoMeshSetRecombine
+
+  !> Set a smoothing meshing constraint on the entity of dimension `dim' and tag
+  !! `tag' in the built-in CAD kernel representation. `val' iterations of a
+  !! Laplace smoother are applied.
+  subroutine gmshModelGeoMeshSetSmoothing(dim, &
+                                          tag, &
+                                          val, &
+                                          ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     val, &
+                     ierr_) &
+      bind(C, name="gmshModelGeoMeshSetSmoothing")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: val
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    integer, intent(in) :: val
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         val=int(val, c_int), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelGeoMeshSetSmoothing
+
+  !> Set a reverse meshing constraint on the entity of dimension `dim' and tag
+  !! `tag' in the built-in CAD kernel representation. 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 geometry). If
+  !! `val' is false, the mesh is left as-is.
+  subroutine gmshModelGeoMeshSetReverse(dim, &
+                                        tag, &
+                                        val, &
+                                        ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     val, &
+                     ierr_) &
+      bind(C, name="gmshModelGeoMeshSetReverse")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: val
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    logical, intent(in), optional :: val
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         val=optval_c_bool(.true., val), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelGeoMeshSetReverse
+
+  !> Set the meshing algorithm on the entity of dimension `dim' and tag `tag' in
+  !! the built-in CAD kernel representation. Currently only supported for `dim'
+  !! == 2.
+  subroutine gmshModelGeoMeshSetAlgorithm(dim, &
+                                          tag, &
+                                          val, &
+                                          ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     val, &
+                     ierr_) &
+      bind(C, name="gmshModelGeoMeshSetAlgorithm")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: val
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    integer, intent(in) :: val
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         val=int(val, c_int), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelGeoMeshSetAlgorithm
+
+  !> Force the mesh size to be extended from the boundary, or not, for the
+  !! entity of dimension `dim' and tag `tag' in the built-in CAD kernel
+  !! representation. Currently only supported for `dim' == 2.
+  subroutine gmshModelGeoMeshSetSizeFromBoundary(dim, &
+                                                 tag, &
+                                                 val, &
+                                                 ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     val, &
+                     ierr_) &
+      bind(C, name="gmshModelGeoMeshSetSizeFromBoundary")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: val
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    integer, intent(in) :: val
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         val=int(val, c_int), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelGeoMeshSetSizeFromBoundary
+
+  !> Add a geometrical point in the OpenCASCADE CAD representation, at
+  !! coordinates (`x', `y', `z'). If `meshSize' is > 0, add a meshing constraint
+  !! at that point. If `tag' is positive, set the tag explicitly; otherwise a
+  !! new tag is selected automatically. Return the tag of the point. (Note that
+  !! the point will be added in the current model only after `synchronize' is
+  !! called. This behavior holds for all the entities added in the occ module.)
+  function gmshModelOccAddPoint(x, &
+                                y, &
+                                z, &
+                                meshSize, &
+                                tag, &
+                                ierr)
+    interface
+    function C_API(x, &
+                   y, &
+                   z, &
+                   meshSize, &
+                   tag, &
+                   ierr_) &
+      bind(C, name="gmshModelOccAddPoint")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      real(c_double), value, intent(in) :: x
+      real(c_double), value, intent(in) :: y
+      real(c_double), value, intent(in) :: z
+      real(c_double), value, intent(in) :: meshSize
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelOccAddPoint
+    real(c_double), intent(in) :: x
+    real(c_double), intent(in) :: y
+    real(c_double), intent(in) :: z
+    real(c_double), intent(in), optional :: meshSize
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelOccAddPoint = C_API(x=real(x, c_double), &
+                           y=real(y, c_double), &
+                           z=real(z, c_double), &
+                           meshSize=optval_c_double(0., meshSize), &
+                           tag=optval_c_int(-1, tag), &
+                           ierr_=ierr)
+    ! Post processing
+  end function gmshModelOccAddPoint
+
+  !> Add a straight line segment in the OpenCASCADE CAD representation, between
+  !! the two points with tags `startTag' and `endTag'. If `tag' is positive, set
+  !! the tag explicitly; otherwise a new tag is selected automatically. Return
+  !! the tag of the line.
+  function gmshModelOccAddLine(startTag, &
+                               endTag, &
+                               tag, &
+                               ierr)
+    interface
+    function C_API(startTag, &
+                   endTag, &
+                   tag, &
+                   ierr_) &
+      bind(C, name="gmshModelOccAddLine")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), value, intent(in) :: startTag
+      integer(c_int), value, intent(in) :: endTag
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelOccAddLine
+    integer, intent(in) :: startTag
+    integer, intent(in) :: endTag
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelOccAddLine = C_API(startTag=int(startTag, c_int), &
+                          endTag=int(endTag, c_int), &
+                          tag=optval_c_int(-1, tag), &
+                          ierr_=ierr)
+    ! Post processing
+  end function gmshModelOccAddLine
+
+  !> Add a circle arc in the OpenCASCADE CAD representation, between the two
+  !! points with tags `startTag' and `endTag', with center `centerTag'. If `tag'
+  !! is positive, set the tag explicitly; otherwise a new tag is selected
+  !! automatically. Return the tag of the circle arc.
+  function gmshModelOccAddCircleArc(startTag, &
+                                    centerTag, &
+                                    endTag, &
+                                    tag, &
+                                    ierr)
+    interface
+    function C_API(startTag, &
+                   centerTag, &
+                   endTag, &
+                   tag, &
+                   ierr_) &
+      bind(C, name="gmshModelOccAddCircleArc")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), value, intent(in) :: startTag
+      integer(c_int), value, intent(in) :: centerTag
+      integer(c_int), value, intent(in) :: endTag
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelOccAddCircleArc
+    integer, intent(in) :: startTag
+    integer, intent(in) :: centerTag
+    integer, intent(in) :: endTag
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelOccAddCircleArc = C_API(startTag=int(startTag, c_int), &
+                               centerTag=int(centerTag, c_int), &
+                               endTag=int(endTag, c_int), &
+                               tag=optval_c_int(-1, tag), &
+                               ierr_=ierr)
+    ! Post processing
+  end function gmshModelOccAddCircleArc
+
+  !> Add a circle of center (`x', `y', `z') and radius `r' in the OpenCASCADE
+  !! CAD representation. If `tag' is positive, set the tag explicitly; otherwise
+  !! a new tag is selected automatically. If `angle1' and `angle2' are
+  !! specified, create a circle arc between the two angles. If a vector `zAxis'
+  !! of size 3 is provided, use it as the normal to the circle plane (z-axis).
+  !! If a vector `xAxis' of size 3 is provided in addition to `zAxis', use it to
+  !! define the x-axis. Return the tag of the circle.
+  function gmshModelOccAddCircle(x, &
+                                 y, &
+                                 z, &
+                                 r, &
+                                 tag, &
+                                 angle1, &
+                                 angle2, &
+                                 zAxis, &
+                                 xAxis, &
+                                 ierr)
+    interface
+    function C_API(x, &
+                   y, &
+                   z, &
+                   r, &
+                   tag, &
+                   angle1, &
+                   angle2, &
+                   api_zAxis_, &
+                   api_zAxis_n_, &
+                   api_xAxis_, &
+                   api_xAxis_n_, &
+                   ierr_) &
+      bind(C, name="gmshModelOccAddCircle")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      real(c_double), value, intent(in) :: x
+      real(c_double), value, intent(in) :: y
+      real(c_double), value, intent(in) :: z
+      real(c_double), value, intent(in) :: r
+      integer(c_int), value, intent(in) :: tag
+      real(c_double), value, intent(in) :: angle1
+      real(c_double), value, intent(in) :: angle2
+      real(c_double), dimension(*), optional :: api_zAxis_
+      integer(c_size_t), value, intent(in) :: api_zAxis_n_
+      real(c_double), dimension(*), optional :: api_xAxis_
+      integer(c_size_t), value, intent(in) :: api_xAxis_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelOccAddCircle
+    real(c_double), intent(in) :: x
+    real(c_double), intent(in) :: y
+    real(c_double), intent(in) :: z
+    real(c_double), intent(in) :: r
+    integer, intent(in), optional :: tag
+    real(c_double), intent(in), optional :: angle1
+    real(c_double), intent(in), optional :: angle2
+    real(c_double), dimension(:), intent(in), optional :: zAxis
+    real(c_double), dimension(:), intent(in), optional :: xAxis
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelOccAddCircle = C_API(x=real(x, c_double), &
+                            y=real(y, c_double), &
+                            z=real(z, c_double), &
+                            r=real(r, c_double), &
+                            tag=optval_c_int(-1, tag), &
+                            angle1=optval_c_double(0., angle1), &
+                            angle2=optval_c_double(2*M_PI, angle2), &
+                            api_zAxis_=zAxis, &
+                            api_zAxis_n_=size_gmsh_double(zAxis), &
+                            api_xAxis_=xAxis, &
+                            api_xAxis_n_=size_gmsh_double(xAxis), &
+                            ierr_=ierr)
+    ! Post processing
+  end function gmshModelOccAddCircle
+
+  !> Add an ellipse arc in the OpenCASCADE CAD representation, between the two
+  !! points `startTag' and `endTag', and with center `centerTag' and major axis
+  !! point `majorTag'. If `tag' is positive, set the tag explicitly; otherwise a
+  !! new tag is selected automatically. Return the tag of the ellipse arc. Note
+  !! that OpenCASCADE does not allow creating ellipse arcs with the major radius
+  !! smaller than the minor radius.
+  function gmshModelOccAddEllipseArc(startTag, &
+                                     centerTag, &
+                                     majorTag, &
+                                     endTag, &
+                                     tag, &
+                                     ierr)
+    interface
+    function C_API(startTag, &
+                   centerTag, &
+                   majorTag, &
+                   endTag, &
+                   tag, &
+                   ierr_) &
+      bind(C, name="gmshModelOccAddEllipseArc")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), value, intent(in) :: startTag
+      integer(c_int), value, intent(in) :: centerTag
+      integer(c_int), value, intent(in) :: majorTag
+      integer(c_int), value, intent(in) :: endTag
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelOccAddEllipseArc
+    integer, intent(in) :: startTag
+    integer, intent(in) :: centerTag
+    integer, intent(in) :: majorTag
+    integer, intent(in) :: endTag
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelOccAddEllipseArc = C_API(startTag=int(startTag, c_int), &
+                                centerTag=int(centerTag, c_int), &
+                                majorTag=int(majorTag, c_int), &
+                                endTag=int(endTag, c_int), &
+                                tag=optval_c_int(-1, tag), &
+                                ierr_=ierr)
+    ! Post processing
+  end function gmshModelOccAddEllipseArc
+
+  !> Add an ellipse of center (`x', `y', `z') and radii `r1' and `r2' (with `r1'
+  !! >= `r2') along the x- and y-axes, respectively, in the OpenCASCADE CAD
+  !! representation. If `tag' is positive, set the tag explicitly; otherwise a
+  !! new tag is selected automatically. If `angle1' and `angle2' are specified,
+  !! create an ellipse arc between the two angles. If a vector `zAxis' of size 3
+  !! is provided, use it as the normal to the ellipse plane (z-axis). If a
+  !! vector `xAxis' of size 3 is provided in addition to `zAxis', use it to
+  !! define the x-axis. Return the tag of the ellipse.
+  function gmshModelOccAddEllipse(x, &
+                                  y, &
+                                  z, &
+                                  r1, &
+                                  r2, &
+                                  tag, &
+                                  angle1, &
+                                  angle2, &
+                                  zAxis, &
+                                  xAxis, &
+                                  ierr)
+    interface
+    function C_API(x, &
+                   y, &
+                   z, &
+                   r1, &
+                   r2, &
+                   tag, &
+                   angle1, &
+                   angle2, &
+                   api_zAxis_, &
+                   api_zAxis_n_, &
+                   api_xAxis_, &
+                   api_xAxis_n_, &
+                   ierr_) &
+      bind(C, name="gmshModelOccAddEllipse")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      real(c_double), value, intent(in) :: x
+      real(c_double), value, intent(in) :: y
+      real(c_double), value, intent(in) :: z
+      real(c_double), value, intent(in) :: r1
+      real(c_double), value, intent(in) :: r2
+      integer(c_int), value, intent(in) :: tag
+      real(c_double), value, intent(in) :: angle1
+      real(c_double), value, intent(in) :: angle2
+      real(c_double), dimension(*), optional :: api_zAxis_
+      integer(c_size_t), value, intent(in) :: api_zAxis_n_
+      real(c_double), dimension(*), optional :: api_xAxis_
+      integer(c_size_t), value, intent(in) :: api_xAxis_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelOccAddEllipse
+    real(c_double), intent(in) :: x
+    real(c_double), intent(in) :: y
+    real(c_double), intent(in) :: z
+    real(c_double), intent(in) :: r1
+    real(c_double), intent(in) :: r2
+    integer, intent(in), optional :: tag
+    real(c_double), intent(in), optional :: angle1
+    real(c_double), intent(in), optional :: angle2
+    real(c_double), dimension(:), intent(in), optional :: zAxis
+    real(c_double), dimension(:), intent(in), optional :: xAxis
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelOccAddEllipse = C_API(x=real(x, c_double), &
+                             y=real(y, c_double), &
+                             z=real(z, c_double), &
+                             r1=real(r1, c_double), &
+                             r2=real(r2, c_double), &
+                             tag=optval_c_int(-1, tag), &
+                             angle1=optval_c_double(0., angle1), &
+                             angle2=optval_c_double(2*M_PI, angle2), &
+                             api_zAxis_=zAxis, &
+                             api_zAxis_n_=size_gmsh_double(zAxis), &
+                             api_xAxis_=xAxis, &
+                             api_xAxis_n_=size_gmsh_double(xAxis), &
+                             ierr_=ierr)
+    ! Post processing
+  end function gmshModelOccAddEllipse
+
+  !> Add a spline (C2 b-spline) curve in the OpenCASCADE CAD representation,
+  !! going through the points `pointTags'. If `tag' is positive, set the tag
+  !! explicitly; otherwise a new tag is selected automatically. Create a
+  !! periodic curve if the first and last points are the same. Return the tag of
+  !! the spline curve.
+  function gmshModelOccAddSpline(pointTags, &
+                                 tag, &
+                                 ierr)
+    interface
+    function C_API(api_pointTags_, &
+                   api_pointTags_n_, &
+                   tag, &
+                   ierr_) &
+      bind(C, name="gmshModelOccAddSpline")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), dimension(*) :: api_pointTags_
+      integer(c_size_t), value, intent(in) :: api_pointTags_n_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelOccAddSpline
+    integer(c_int), dimension(:), intent(in) :: pointTags
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelOccAddSpline = C_API(api_pointTags_=pointTags, &
+                            api_pointTags_n_=size_gmsh_int(pointTags), &
+                            tag=optval_c_int(-1, tag), &
+                            ierr_=ierr)
+    ! Post processing
+  end function gmshModelOccAddSpline
+
+  !> Add a b-spline curve of degree `degree' in the OpenCASCADE CAD
+  !! representation, with `pointTags' control points. If `weights', `knots' or
+  !! `multiplicities' are not provided, default parameters are computed
+  !! automatically. If `tag' is positive, set the tag explicitly; otherwise a
+  !! new tag is selected automatically. Create a periodic curve if the first and
+  !! last points are the same. Return the tag of the b-spline curve.
+  function gmshModelOccAddBSpline(pointTags, &
+                                  tag, &
+                                  degree, &
+                                  weights, &
+                                  knots, &
+                                  multiplicities, &
+                                  ierr)
+    interface
+    function C_API(api_pointTags_, &
+                   api_pointTags_n_, &
+                   tag, &
+                   degree, &
+                   api_weights_, &
+                   api_weights_n_, &
+                   api_knots_, &
+                   api_knots_n_, &
+                   api_multiplicities_, &
+                   api_multiplicities_n_, &
+                   ierr_) &
+      bind(C, name="gmshModelOccAddBSpline")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), dimension(*) :: api_pointTags_
+      integer(c_size_t), value, intent(in) :: api_pointTags_n_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: degree
+      real(c_double), dimension(*), optional :: api_weights_
+      integer(c_size_t), value, intent(in) :: api_weights_n_
+      real(c_double), dimension(*), optional :: api_knots_
+      integer(c_size_t), value, intent(in) :: api_knots_n_
+      integer(c_int), dimension(*), optional :: api_multiplicities_
+      integer(c_size_t), value, intent(in) :: api_multiplicities_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelOccAddBSpline
+    integer(c_int), dimension(:), intent(in) :: pointTags
+    integer, intent(in), optional :: tag
+    integer, intent(in), optional :: degree
+    real(c_double), dimension(:), intent(in), optional :: weights
+    real(c_double), dimension(:), intent(in), optional :: knots
+    integer(c_int), dimension(:), intent(in), optional :: multiplicities
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelOccAddBSpline = C_API(api_pointTags_=pointTags, &
+                             api_pointTags_n_=size_gmsh_int(pointTags), &
+                             tag=optval_c_int(-1, tag), &
+                             degree=optval_c_int(3, degree), &
+                             api_weights_=weights, &
+                             api_weights_n_=size_gmsh_double(weights), &
+                             api_knots_=knots, &
+                             api_knots_n_=size_gmsh_double(knots), &
+                             api_multiplicities_=multiplicities, &
+                             api_multiplicities_n_=size_gmsh_int(multiplicities), &
+                             ierr_=ierr)
+    ! Post processing
+  end function gmshModelOccAddBSpline
+
+  !> Add a Bezier curve in the OpenCASCADE CAD representation, with `pointTags'
+  !! control points. If `tag' is positive, set the tag explicitly; otherwise a
+  !! new tag is selected automatically. Return the tag of the Bezier curve.
+  function gmshModelOccAddBezier(pointTags, &
+                                 tag, &
+                                 ierr)
+    interface
+    function C_API(api_pointTags_, &
+                   api_pointTags_n_, &
+                   tag, &
+                   ierr_) &
+      bind(C, name="gmshModelOccAddBezier")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), dimension(*) :: api_pointTags_
+      integer(c_size_t), value, intent(in) :: api_pointTags_n_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelOccAddBezier
+    integer(c_int), dimension(:), intent(in) :: pointTags
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelOccAddBezier = C_API(api_pointTags_=pointTags, &
+                            api_pointTags_n_=size_gmsh_int(pointTags), &
+                            tag=optval_c_int(-1, tag), &
+                            ierr_=ierr)
+    ! Post processing
+  end function gmshModelOccAddBezier
+
+  !> Add a wire (open or closed) in the OpenCASCADE CAD representation, formed
+  !! by the curves `curveTags'. Note that an OpenCASCADE wire can be made of
+  !! curves that share geometrically identical (but topologically different)
+  !! points. If `tag' is positive, set the tag explicitly; otherwise a new tag
+  !! is selected automatically. Return the tag of the wire.
+  function gmshModelOccAddWire(curveTags, &
+                               tag, &
+                               checkClosed, &
+                               ierr)
+    interface
+    function C_API(api_curveTags_, &
+                   api_curveTags_n_, &
+                   tag, &
+                   checkClosed, &
+                   ierr_) &
+      bind(C, name="gmshModelOccAddWire")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), dimension(*) :: api_curveTags_
+      integer(c_size_t), value, intent(in) :: api_curveTags_n_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: checkClosed
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelOccAddWire
+    integer(c_int), dimension(:), intent(in) :: curveTags
+    integer, intent(in), optional :: tag
+    logical, intent(in), optional :: checkClosed
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelOccAddWire = C_API(api_curveTags_=curveTags, &
+                          api_curveTags_n_=size_gmsh_int(curveTags), &
+                          tag=optval_c_int(-1, tag), &
+                          checkClosed=optval_c_bool(.false., checkClosed), &
+                          ierr_=ierr)
+    ! Post processing
+  end function gmshModelOccAddWire
+
+  !> Add a curve loop (a closed wire) in the OpenCASCADE CAD representation,
+  !! formed by the curves `curveTags'. `curveTags' should contain tags of curves
+  !! forming a closed loop. Negative tags can be specified for compatibility
+  !! with the built-in kernel, but are simply ignored: the wire is oriented
+  !! according to the orientation of its first curve. Note that an OpenCASCADE
+  !! curve loop can be made of curves that share geometrically identical (but
+  !! topologically different) points. If `tag' is positive, set the tag
+  !! explicitly; otherwise a new tag is selected automatically. Return the tag
+  !! of the curve loop.
+  function gmshModelOccAddCurveLoop(curveTags, &
+                                    tag, &
+                                    ierr)
+    interface
+    function C_API(api_curveTags_, &
+                   api_curveTags_n_, &
+                   tag, &
+                   ierr_) &
+      bind(C, name="gmshModelOccAddCurveLoop")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), dimension(*) :: api_curveTags_
+      integer(c_size_t), value, intent(in) :: api_curveTags_n_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelOccAddCurveLoop
+    integer(c_int), dimension(:), intent(in) :: curveTags
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelOccAddCurveLoop = C_API(api_curveTags_=curveTags, &
+                               api_curveTags_n_=size_gmsh_int(curveTags), &
+                               tag=optval_c_int(-1, tag), &
+                               ierr_=ierr)
+    ! Post processing
+  end function gmshModelOccAddCurveLoop
+
+  !> Add a rectangle in the OpenCASCADE CAD representation, with lower left
+  !! corner at (`x', `y', `z') and upper right corner at (`x' + `dx', `y' +
+  !! `dy', `z'). If `tag' is positive, set the tag explicitly; otherwise a new
+  !! tag is selected automatically. Round the corners if `roundedRadius' is
+  !! nonzero. Return the tag of the rectangle.
+  function gmshModelOccAddRectangle(x, &
+                                    y, &
+                                    z, &
+                                    dx, &
+                                    dy, &
+                                    tag, &
+                                    roundedRadius, &
+                                    ierr)
+    interface
+    function C_API(x, &
+                   y, &
+                   z, &
+                   dx, &
+                   dy, &
+                   tag, &
+                   roundedRadius, &
+                   ierr_) &
+      bind(C, name="gmshModelOccAddRectangle")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      real(c_double), value, intent(in) :: x
+      real(c_double), value, intent(in) :: y
+      real(c_double), value, intent(in) :: z
+      real(c_double), value, intent(in) :: dx
+      real(c_double), value, intent(in) :: dy
+      integer(c_int), value, intent(in) :: tag
+      real(c_double), value, intent(in) :: roundedRadius
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelOccAddRectangle
+    real(c_double), intent(in) :: x
+    real(c_double), intent(in) :: y
+    real(c_double), intent(in) :: z
+    real(c_double), intent(in) :: dx
+    real(c_double), intent(in) :: dy
+    integer, intent(in), optional :: tag
+    real(c_double), intent(in), optional :: roundedRadius
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelOccAddRectangle = C_API(x=real(x, c_double), &
+                               y=real(y, c_double), &
+                               z=real(z, c_double), &
+                               dx=real(dx, c_double), &
+                               dy=real(dy, c_double), &
+                               tag=optval_c_int(-1, tag), &
+                               roundedRadius=optval_c_double(0., roundedRadius), &
+                               ierr_=ierr)
+    ! Post processing
+  end function gmshModelOccAddRectangle
+
+  !> Add a disk in the OpenCASCADE CAD representation, with center (`xc', `yc',
+  !! `zc') and radius `rx' along the x-axis and `ry' along the y-axis (`rx' >=
+  !! `ry'). If `tag' is positive, set the tag explicitly; otherwise a new tag is
+  !! selected automatically. If a vector `zAxis' of size 3 is provided, use it
+  !! as the normal to the disk (z-axis). If a vector `xAxis' of size 3 is
+  !! provided in addition to `zAxis', use it to define the x-axis. Return the
+  !! tag of the disk.
+  function gmshModelOccAddDisk(xc, &
+                               yc, &
+                               zc, &
+                               rx, &
+                               ry, &
+                               tag, &
+                               zAxis, &
+                               xAxis, &
+                               ierr)
+    interface
+    function C_API(xc, &
+                   yc, &
+                   zc, &
+                   rx, &
+                   ry, &
+                   tag, &
+                   api_zAxis_, &
+                   api_zAxis_n_, &
+                   api_xAxis_, &
+                   api_xAxis_n_, &
+                   ierr_) &
+      bind(C, name="gmshModelOccAddDisk")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      real(c_double), value, intent(in) :: xc
+      real(c_double), value, intent(in) :: yc
+      real(c_double), value, intent(in) :: zc
+      real(c_double), value, intent(in) :: rx
+      real(c_double), value, intent(in) :: ry
+      integer(c_int), value, intent(in) :: tag
+      real(c_double), dimension(*), optional :: api_zAxis_
+      integer(c_size_t), value, intent(in) :: api_zAxis_n_
+      real(c_double), dimension(*), optional :: api_xAxis_
+      integer(c_size_t), value, intent(in) :: api_xAxis_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelOccAddDisk
+    real(c_double), intent(in) :: xc
+    real(c_double), intent(in) :: yc
+    real(c_double), intent(in) :: zc
+    real(c_double), intent(in) :: rx
+    real(c_double), intent(in) :: ry
+    integer, intent(in), optional :: tag
+    real(c_double), dimension(:), intent(in), optional :: zAxis
+    real(c_double), dimension(:), intent(in), optional :: xAxis
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelOccAddDisk = C_API(xc=real(xc, c_double), &
+                          yc=real(yc, c_double), &
+                          zc=real(zc, c_double), &
+                          rx=real(rx, c_double), &
+                          ry=real(ry, c_double), &
+                          tag=optval_c_int(-1, tag), &
+                          api_zAxis_=zAxis, &
+                          api_zAxis_n_=size_gmsh_double(zAxis), &
+                          api_xAxis_=xAxis, &
+                          api_xAxis_n_=size_gmsh_double(xAxis), &
+                          ierr_=ierr)
+    ! Post processing
+  end function gmshModelOccAddDisk
+
+  !> Add a plane surface in the OpenCASCADE CAD representation, defined by one
+  !! or more curve loops (or closed wires) `wireTags'. The first curve loop
+  !! defines the exterior contour; additional curve loop define holes. If `tag'
+  !! is positive, set the tag explicitly; otherwise a new tag is selected
+  !! automatically. Return the tag of the surface.
+  function gmshModelOccAddPlaneSurface(wireTags, &
+                                       tag, &
+                                       ierr)
+    interface
+    function C_API(api_wireTags_, &
+                   api_wireTags_n_, &
+                   tag, &
+                   ierr_) &
+      bind(C, name="gmshModelOccAddPlaneSurface")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), dimension(*) :: api_wireTags_
+      integer(c_size_t), value, intent(in) :: api_wireTags_n_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelOccAddPlaneSurface
+    integer(c_int), dimension(:), intent(in) :: wireTags
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelOccAddPlaneSurface = C_API(api_wireTags_=wireTags, &
+                                  api_wireTags_n_=size_gmsh_int(wireTags), &
+                                  tag=optval_c_int(-1, tag), &
+                                  ierr_=ierr)
+    ! Post processing
+  end function gmshModelOccAddPlaneSurface
+
+  !> Add a surface in the OpenCASCADE CAD representation, filling the curve loop
+  !! `wireTag'. If `tag' is positive, set the tag explicitly; otherwise a new
+  !! tag is selected automatically. Return the tag of the surface. If
+  !! `pointTags' are provided, force the surface to pass through the given
+  !! points. The other optional arguments are `degree' (the degree of the energy
+  !! criterion to minimize for computing the deformation of the surface),
+  !! `numPointsOnCurves' (the average number of points for discretisation of the
+  !! bounding curves), `numIter' (the maximum number of iterations of the
+  !! optimization process), `anisotropic' (improve performance when the ratio of
+  !! the length along the two parametric coordinates of the surface is high),
+  !! `tol2d' (tolerance to the constraints in the parametric plane of the
+  !! surface), `tol3d' (the maximum distance allowed between the support surface
+  !! and the constraints), `tolAng' (the maximum angle allowed between the
+  !! normal of the surface and the constraints), `tolCurv' (the maximum
+  !! difference of curvature allowed between the surface and the constraint),
+  !! `maxDegree' (the highest degree which the polynomial defining the filling
+  !! surface can have) and, `maxSegments' (the largest number of segments which
+  !! the filling surface can have).
+  function gmshModelOccAddSurfaceFilling(wireTag, &
+                                         tag, &
+                                         pointTags, &
+                                         degree, &
+                                         numPointsOnCurves, &
+                                         numIter, &
+                                         anisotropic, &
+                                         tol2d, &
+                                         tol3d, &
+                                         tolAng, &
+                                         tolCurv, &
+                                         maxDegree, &
+                                         maxSegments, &
+                                         ierr)
+    interface
+    function C_API(wireTag, &
+                   tag, &
+                   api_pointTags_, &
+                   api_pointTags_n_, &
+                   degree, &
+                   numPointsOnCurves, &
+                   numIter, &
+                   anisotropic, &
+                   tol2d, &
+                   tol3d, &
+                   tolAng, &
+                   tolCurv, &
+                   maxDegree, &
+                   maxSegments, &
+                   ierr_) &
+      bind(C, name="gmshModelOccAddSurfaceFilling")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), value, intent(in) :: wireTag
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), dimension(*), optional :: api_pointTags_
+      integer(c_size_t), value, intent(in) :: api_pointTags_n_
+      integer(c_int), value, intent(in) :: degree
+      integer(c_int), value, intent(in) :: numPointsOnCurves
+      integer(c_int), value, intent(in) :: numIter
+      integer(c_int), value, intent(in) :: anisotropic
+      real(c_double), value, intent(in) :: tol2d
+      real(c_double), value, intent(in) :: tol3d
+      real(c_double), value, intent(in) :: tolAng
+      real(c_double), value, intent(in) :: tolCurv
+      integer(c_int), value, intent(in) :: maxDegree
+      integer(c_int), value, intent(in) :: maxSegments
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelOccAddSurfaceFilling
+    integer, intent(in) :: wireTag
+    integer, intent(in), optional :: tag
+    integer(c_int), dimension(:), intent(in), optional :: pointTags
+    integer, intent(in), optional :: degree
+    integer, intent(in), optional :: numPointsOnCurves
+    integer, intent(in), optional :: numIter
+    logical, intent(in), optional :: anisotropic
+    real(c_double), intent(in), optional :: tol2d
+    real(c_double), intent(in), optional :: tol3d
+    real(c_double), intent(in), optional :: tolAng
+    real(c_double), intent(in), optional :: tolCurv
+    integer, intent(in), optional :: maxDegree
+    integer, intent(in), optional :: maxSegments
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelOccAddSurfaceFilling = C_API(wireTag=int(wireTag, c_int), &
+                                    tag=optval_c_int(-1, tag), &
+                                    api_pointTags_=pointTags, &
+                                    api_pointTags_n_=size_gmsh_int(pointTags), &
+                                    degree=optval_c_int(3, degree), &
+                                    numPointsOnCurves=optval_c_int(15, numPointsOnCurves), &
+                                    numIter=optval_c_int(2, numIter), &
+                                    anisotropic=optval_c_bool(.false., anisotropic), &
+                                    tol2d=optval_c_double(0.00001, tol2d), &
+                                    tol3d=optval_c_double(0.0001, tol3d), &
+                                    tolAng=optval_c_double(0.01, tolAng), &
+                                    tolCurv=optval_c_double(0.1, tolCurv), &
+                                    maxDegree=optval_c_int(8, maxDegree), &
+                                    maxSegments=optval_c_int(9, maxSegments), &
+                                    ierr_=ierr)
+    ! Post processing
+  end function gmshModelOccAddSurfaceFilling
+
+  !> Add a BSpline surface in the OpenCASCADE CAD representation, filling the
+  !! curve loop `wireTag'. The curve loop should be made of 2, 3 or 4 curves.
+  !! The optional `type' argument specifies the type of filling: "Stretch"
+  !! creates the flattest patch, "Curved" (the default) creates the most rounded
+  !! patch, and "Coons" creates a rounded patch with less depth than "Curved".
+  !! If `tag' is positive, set the tag explicitly; otherwise a new tag is
+  !! selected automatically. Return the tag of the surface.
+  function gmshModelOccAddBSplineFilling(wireTag, &
+                                         tag, &
+                                         type, &
+                                         ierr)
+    interface
+    function C_API(wireTag, &
+                   tag, &
+                   type, &
+                   ierr_) &
+      bind(C, name="gmshModelOccAddBSplineFilling")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), value, intent(in) :: wireTag
+      integer(c_int), value, intent(in) :: tag
+      character(len=1, kind=c_char), dimension(*), intent(in), optional :: type
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelOccAddBSplineFilling
+    integer, intent(in) :: wireTag
+    integer, intent(in), optional :: tag
+    character(len=*), intent(in), optional :: type
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelOccAddBSplineFilling = C_API(wireTag=int(wireTag, c_int), &
+                                    tag=optval_c_int(-1, tag), &
+                                    type=istring_(optval_c_str("", type)), &
+                                    ierr_=ierr)
+    ! Post processing
+  end function gmshModelOccAddBSplineFilling
+
+  !> Add a Bezier surface in the OpenCASCADE CAD representation, filling the
+  !! curve loop `wireTag'. The curve loop should be made of 2, 3 or 4 Bezier
+  !! curves. The optional `type' argument specifies the type of filling:
+  !! "Stretch" creates the flattest patch, "Curved" (the default) creates the
+  !! most rounded patch, and "Coons" creates a rounded patch with less depth
+  !! than "Curved". If `tag' is positive, set the tag explicitly; otherwise a
+  !! new tag is selected automatically. Return the tag of the surface.
+  function gmshModelOccAddBezierFilling(wireTag, &
+                                        tag, &
+                                        type, &
+                                        ierr)
+    interface
+    function C_API(wireTag, &
+                   tag, &
+                   type, &
+                   ierr_) &
+      bind(C, name="gmshModelOccAddBezierFilling")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), value, intent(in) :: wireTag
+      integer(c_int), value, intent(in) :: tag
+      character(len=1, kind=c_char), dimension(*), intent(in), optional :: type
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelOccAddBezierFilling
+    integer, intent(in) :: wireTag
+    integer, intent(in), optional :: tag
+    character(len=*), intent(in), optional :: type
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelOccAddBezierFilling = C_API(wireTag=int(wireTag, c_int), &
+                                   tag=optval_c_int(-1, tag), &
+                                   type=istring_(optval_c_str("", type)), &
+                                   ierr_=ierr)
+    ! Post processing
+  end function gmshModelOccAddBezierFilling
+
+  !> Add a b-spline surface of degree `degreeU' x `degreeV' in the OpenCASCADE
+  !! CAD representation, with `pointTags' control points given as a single
+  !! vector [Pu1v1, ... Pu`numPointsU'v1, Pu1v2, ...]. If `weights', `knotsU',
+  !! `knotsV', `multiplicitiesU' or `multiplicitiesV' are not provided, default
+  !! parameters are computed automatically. If `tag' is positive, set the tag
+  !! explicitly; otherwise a new tag is selected automatically. If `wireTags' is
+  !! provided, trim the b-spline patch using the provided wires: the first wire
+  !! defines the external contour, the others define holes. If `wire3D' is set,
+  !! consider wire curves as 3D curves and project them on the b-spline surface;
+  !! otherwise consider the wire curves as defined in the parametric space of
+  !! the surface. Return the tag of the b-spline surface.
+  function gmshModelOccAddBSplineSurface(pointTags, &
+                                         numPointsU, &
+                                         tag, &
+                                         degreeU, &
+                                         degreeV, &
+                                         weights, &
+                                         knotsU, &
+                                         knotsV, &
+                                         multiplicitiesU, &
+                                         multiplicitiesV, &
+                                         wireTags, &
+                                         wire3D, &
+                                         ierr)
+    interface
+    function C_API(api_pointTags_, &
+                   api_pointTags_n_, &
+                   numPointsU, &
+                   tag, &
+                   degreeU, &
+                   degreeV, &
+                   api_weights_, &
+                   api_weights_n_, &
+                   api_knotsU_, &
+                   api_knotsU_n_, &
+                   api_knotsV_, &
+                   api_knotsV_n_, &
+                   api_multiplicitiesU_, &
+                   api_multiplicitiesU_n_, &
+                   api_multiplicitiesV_, &
+                   api_multiplicitiesV_n_, &
+                   api_wireTags_, &
+                   api_wireTags_n_, &
+                   wire3D, &
+                   ierr_) &
+      bind(C, name="gmshModelOccAddBSplineSurface")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), dimension(*) :: api_pointTags_
+      integer(c_size_t), value, intent(in) :: api_pointTags_n_
+      integer(c_int), value, intent(in) :: numPointsU
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: degreeU
+      integer(c_int), value, intent(in) :: degreeV
+      real(c_double), dimension(*), optional :: api_weights_
+      integer(c_size_t), value, intent(in) :: api_weights_n_
+      real(c_double), dimension(*), optional :: api_knotsU_
+      integer(c_size_t), value, intent(in) :: api_knotsU_n_
+      real(c_double), dimension(*), optional :: api_knotsV_
+      integer(c_size_t), value, intent(in) :: api_knotsV_n_
+      integer(c_int), dimension(*), optional :: api_multiplicitiesU_
+      integer(c_size_t), value, intent(in) :: api_multiplicitiesU_n_
+      integer(c_int), dimension(*), optional :: api_multiplicitiesV_
+      integer(c_size_t), value, intent(in) :: api_multiplicitiesV_n_
+      integer(c_int), dimension(*), optional :: api_wireTags_
+      integer(c_size_t), value, intent(in) :: api_wireTags_n_
+      integer(c_int), value, intent(in) :: wire3D
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelOccAddBSplineSurface
+    integer(c_int), dimension(:), intent(in) :: pointTags
+    integer, intent(in) :: numPointsU
+    integer, intent(in), optional :: tag
+    integer, intent(in), optional :: degreeU
+    integer, intent(in), optional :: degreeV
+    real(c_double), dimension(:), intent(in), optional :: weights
+    real(c_double), dimension(:), intent(in), optional :: knotsU
+    real(c_double), dimension(:), intent(in), optional :: knotsV
+    integer(c_int), dimension(:), intent(in), optional :: multiplicitiesU
+    integer(c_int), dimension(:), intent(in), optional :: multiplicitiesV
+    integer(c_int), dimension(:), intent(in), optional :: wireTags
+    logical, intent(in), optional :: wire3D
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelOccAddBSplineSurface = C_API(api_pointTags_=pointTags, &
+                                    api_pointTags_n_=size_gmsh_int(pointTags), &
+                                    numPointsU=int(numPointsU, c_int), &
+                                    tag=optval_c_int(-1, tag), &
+                                    degreeU=optval_c_int(3, degreeU), &
+                                    degreeV=optval_c_int(3, degreeV), &
+                                    api_weights_=weights, &
+                                    api_weights_n_=size_gmsh_double(weights), &
+                                    api_knotsU_=knotsU, &
+                                    api_knotsU_n_=size_gmsh_double(knotsU), &
+                                    api_knotsV_=knotsV, &
+                                    api_knotsV_n_=size_gmsh_double(knotsV), &
+                                    api_multiplicitiesU_=multiplicitiesU, &
+                                    api_multiplicitiesU_n_=size_gmsh_int(multiplicitiesU), &
+                                    api_multiplicitiesV_=multiplicitiesV, &
+                                    api_multiplicitiesV_n_=size_gmsh_int(multiplicitiesV), &
+                                    api_wireTags_=wireTags, &
+                                    api_wireTags_n_=size_gmsh_int(wireTags), &
+                                    wire3D=optval_c_bool(.false., wire3D), &
+                                    ierr_=ierr)
+    ! Post processing
+  end function gmshModelOccAddBSplineSurface
+
+  !> Add a Bezier surface in the OpenCASCADE CAD representation, with
+  !! `pointTags' control points given as a single vector [Pu1v1, ...
+  !! Pu`numPointsU'v1, Pu1v2, ...]. If `tag' is positive, set the tag
+  !! explicitly; otherwise a new tag is selected automatically. If `wireTags' is
+  !! provided, trim the Bezier patch using the provided wires: the first wire
+  !! defines the external contour, the others define holes. If `wire3D' is set,
+  !! consider wire curves as 3D curves and project them on the Bezier surface;
+  !! otherwise consider the wire curves as defined in the parametric space of
+  !! the surface. Return the tag of the Bezier surface.
+  function gmshModelOccAddBezierSurface(pointTags, &
+                                        numPointsU, &
+                                        tag, &
+                                        wireTags, &
+                                        wire3D, &
+                                        ierr)
+    interface
+    function C_API(api_pointTags_, &
+                   api_pointTags_n_, &
+                   numPointsU, &
+                   tag, &
+                   api_wireTags_, &
+                   api_wireTags_n_, &
+                   wire3D, &
+                   ierr_) &
+      bind(C, name="gmshModelOccAddBezierSurface")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), dimension(*) :: api_pointTags_
+      integer(c_size_t), value, intent(in) :: api_pointTags_n_
+      integer(c_int), value, intent(in) :: numPointsU
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), dimension(*), optional :: api_wireTags_
+      integer(c_size_t), value, intent(in) :: api_wireTags_n_
+      integer(c_int), value, intent(in) :: wire3D
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelOccAddBezierSurface
+    integer(c_int), dimension(:), intent(in) :: pointTags
+    integer, intent(in) :: numPointsU
+    integer, intent(in), optional :: tag
+    integer(c_int), dimension(:), intent(in), optional :: wireTags
+    logical, intent(in), optional :: wire3D
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelOccAddBezierSurface = C_API(api_pointTags_=pointTags, &
+                                   api_pointTags_n_=size_gmsh_int(pointTags), &
+                                   numPointsU=int(numPointsU, c_int), &
+                                   tag=optval_c_int(-1, tag), &
+                                   api_wireTags_=wireTags, &
+                                   api_wireTags_n_=size_gmsh_int(wireTags), &
+                                   wire3D=optval_c_bool(.false., wire3D), &
+                                   ierr_=ierr)
+    ! Post processing
+  end function gmshModelOccAddBezierSurface
+
+  !> Trim the surface `surfaceTag' with the wires `wireTags', replacing any
+  !! existing trimming curves. The first wire defines the external contour, the
+  !! others define holes. If `wire3D' is set, consider wire curves as 3D curves
+  !! and project them on the surface; otherwise consider the wire curves as
+  !! defined in the parametric space of the surface. If `tag' is positive, set
+  !! the tag explicitly; otherwise a new tag is selected automatically. Return
+  !! the tag of the trimmed surface.
+  function gmshModelOccAddTrimmedSurface(surfaceTag, &
+                                         wireTags, &
+                                         wire3D, &
+                                         tag, &
+                                         ierr)
+    interface
+    function C_API(surfaceTag, &
+                   api_wireTags_, &
+                   api_wireTags_n_, &
+                   wire3D, &
+                   tag, &
+                   ierr_) &
+      bind(C, name="gmshModelOccAddTrimmedSurface")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), value, intent(in) :: surfaceTag
+      integer(c_int), dimension(*), optional :: api_wireTags_
+      integer(c_size_t), value, intent(in) :: api_wireTags_n_
+      integer(c_int), value, intent(in) :: wire3D
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelOccAddTrimmedSurface
+    integer, intent(in) :: surfaceTag
+    integer(c_int), dimension(:), intent(in), optional :: wireTags
+    logical, intent(in), optional :: wire3D
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelOccAddTrimmedSurface = C_API(surfaceTag=int(surfaceTag, c_int), &
+                                    api_wireTags_=wireTags, &
+                                    api_wireTags_n_=size_gmsh_int(wireTags), &
+                                    wire3D=optval_c_bool(.false., wire3D), &
+                                    tag=optval_c_int(-1, tag), &
+                                    ierr_=ierr)
+    ! Post processing
+  end function gmshModelOccAddTrimmedSurface
+
+  !> Add a surface loop (a closed shell) in the OpenCASCADE CAD representation,
+  !! formed by `surfaceTags'.  If `tag' is positive, set the tag explicitly;
+  !! otherwise a new tag is selected automatically. Return the tag of the
+  !! surface loop. Setting `sewing' allows one to build a shell made of surfaces
+  !! that share geometrically identical (but topologically different) curves.
+  function gmshModelOccAddSurfaceLoop(surfaceTags, &
+                                      tag, &
+                                      sewing, &
+                                      ierr)
+    interface
+    function C_API(api_surfaceTags_, &
+                   api_surfaceTags_n_, &
+                   tag, &
+                   sewing, &
+                   ierr_) &
+      bind(C, name="gmshModelOccAddSurfaceLoop")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), dimension(*) :: api_surfaceTags_
+      integer(c_size_t), value, intent(in) :: api_surfaceTags_n_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: sewing
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelOccAddSurfaceLoop
+    integer(c_int), dimension(:), intent(in) :: surfaceTags
+    integer, intent(in), optional :: tag
+    logical, intent(in), optional :: sewing
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelOccAddSurfaceLoop = C_API(api_surfaceTags_=surfaceTags, &
+                                 api_surfaceTags_n_=size_gmsh_int(surfaceTags), &
+                                 tag=optval_c_int(-1, tag), &
+                                 sewing=optval_c_bool(.false., sewing), &
+                                 ierr_=ierr)
+    ! Post processing
+  end function gmshModelOccAddSurfaceLoop
+
+  !> Add a volume (a region) in the OpenCASCADE CAD representation, 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, set the tag explicitly; otherwise a new tag is selected
+  !! automatically. Return the tag of the volume.
+  function gmshModelOccAddVolume(shellTags, &
+                                 tag, &
+                                 ierr)
+    interface
+    function C_API(api_shellTags_, &
+                   api_shellTags_n_, &
+                   tag, &
+                   ierr_) &
+      bind(C, name="gmshModelOccAddVolume")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), dimension(*) :: api_shellTags_
+      integer(c_size_t), value, intent(in) :: api_shellTags_n_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelOccAddVolume
+    integer(c_int), dimension(:), intent(in) :: shellTags
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelOccAddVolume = C_API(api_shellTags_=shellTags, &
+                            api_shellTags_n_=size_gmsh_int(shellTags), &
+                            tag=optval_c_int(-1, tag), &
+                            ierr_=ierr)
+    ! Post processing
+  end function gmshModelOccAddVolume
+
+  !> Add a sphere of center (`xc', `yc', `zc') and radius `r' in the OpenCASCADE
+  !! CAD representation. The optional `angle1' and `angle2' arguments define the
+  !! polar angle opening (from -Pi/2 to Pi/2). The optional `angle3' argument
+  !! defines the azimuthal opening (from 0 to 2*Pi). If `tag' is positive, set
+  !! the tag explicitly; otherwise a new tag is selected automatically. Return
+  !! the tag of the sphere.
+  function gmshModelOccAddSphere(xc, &
+                                 yc, &
+                                 zc, &
+                                 radius, &
+                                 tag, &
+                                 angle1, &
+                                 angle2, &
+                                 angle3, &
+                                 ierr)
+    interface
+    function C_API(xc, &
+                   yc, &
+                   zc, &
+                   radius, &
+                   tag, &
+                   angle1, &
+                   angle2, &
+                   angle3, &
+                   ierr_) &
+      bind(C, name="gmshModelOccAddSphere")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      real(c_double), value, intent(in) :: xc
+      real(c_double), value, intent(in) :: yc
+      real(c_double), value, intent(in) :: zc
+      real(c_double), value, intent(in) :: radius
+      integer(c_int), value, intent(in) :: tag
+      real(c_double), value, intent(in) :: angle1
+      real(c_double), value, intent(in) :: angle2
+      real(c_double), value, intent(in) :: angle3
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelOccAddSphere
+    real(c_double), intent(in) :: xc
+    real(c_double), intent(in) :: yc
+    real(c_double), intent(in) :: zc
+    real(c_double), intent(in) :: radius
+    integer, intent(in), optional :: tag
+    real(c_double), intent(in), optional :: angle1
+    real(c_double), intent(in), optional :: angle2
+    real(c_double), intent(in), optional :: angle3
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelOccAddSphere = C_API(xc=real(xc, c_double), &
+                            yc=real(yc, c_double), &
+                            zc=real(zc, c_double), &
+                            radius=real(radius, c_double), &
+                            tag=optval_c_int(-1, tag), &
+                            angle1=optval_c_double(-M_PI/2, angle1), &
+                            angle2=optval_c_double(M_PI/2, angle2), &
+                            angle3=optval_c_double(2*M_PI, angle3), &
+                            ierr_=ierr)
+    ! Post processing
+  end function gmshModelOccAddSphere
+
+  !> Add a parallelepipedic box in the OpenCASCADE CAD representation, defined
+  !! by a point (`x', `y', `z') and the extents along the x-, y- and z-axes. If
+  !! `tag' is positive, set the tag explicitly; otherwise a new tag is selected
+  !! automatically. Return the tag of the box.
+  function gmshModelOccAddBox(x, &
+                              y, &
+                              z, &
+                              dx, &
+                              dy, &
+                              dz, &
+                              tag, &
+                              ierr)
+    interface
+    function C_API(x, &
+                   y, &
+                   z, &
+                   dx, &
+                   dy, &
+                   dz, &
+                   tag, &
+                   ierr_) &
+      bind(C, name="gmshModelOccAddBox")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      real(c_double), value, intent(in) :: x
+      real(c_double), value, intent(in) :: y
+      real(c_double), value, intent(in) :: z
+      real(c_double), value, intent(in) :: dx
+      real(c_double), value, intent(in) :: dy
+      real(c_double), value, intent(in) :: dz
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelOccAddBox
+    real(c_double), intent(in) :: x
+    real(c_double), intent(in) :: y
+    real(c_double), intent(in) :: z
+    real(c_double), intent(in) :: dx
+    real(c_double), intent(in) :: dy
+    real(c_double), intent(in) :: dz
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelOccAddBox = C_API(x=real(x, c_double), &
+                         y=real(y, c_double), &
+                         z=real(z, c_double), &
+                         dx=real(dx, c_double), &
+                         dy=real(dy, c_double), &
+                         dz=real(dz, c_double), &
+                         tag=optval_c_int(-1, tag), &
+                         ierr_=ierr)
+    ! Post processing
+  end function gmshModelOccAddBox
+
+  !> Add a cylinder in the OpenCASCADE CAD representation, defined by the center
+  !! (`x', `y', `z') of its first circular face, the 3 components (`dx', `dy',
+  !! `dz') of the vector defining its axis and its radius `r'. The optional
+  !! `angle' argument defines the angular opening (from 0 to 2*Pi). If `tag' is
+  !! positive, set the tag explicitly; otherwise a new tag is selected
+  !! automatically. Return the tag of the cylinder.
+  function gmshModelOccAddCylinder(x, &
+                                   y, &
+                                   z, &
+                                   dx, &
+                                   dy, &
+                                   dz, &
+                                   r, &
+                                   tag, &
+                                   angle, &
+                                   ierr)
+    interface
+    function C_API(x, &
+                   y, &
+                   z, &
+                   dx, &
+                   dy, &
+                   dz, &
+                   r, &
+                   tag, &
+                   angle, &
+                   ierr_) &
+      bind(C, name="gmshModelOccAddCylinder")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      real(c_double), value, intent(in) :: x
+      real(c_double), value, intent(in) :: y
+      real(c_double), value, intent(in) :: z
+      real(c_double), value, intent(in) :: dx
+      real(c_double), value, intent(in) :: dy
+      real(c_double), value, intent(in) :: dz
+      real(c_double), value, intent(in) :: r
+      integer(c_int), value, intent(in) :: tag
+      real(c_double), value, intent(in) :: angle
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelOccAddCylinder
+    real(c_double), intent(in) :: x
+    real(c_double), intent(in) :: y
+    real(c_double), intent(in) :: z
+    real(c_double), intent(in) :: dx
+    real(c_double), intent(in) :: dy
+    real(c_double), intent(in) :: dz
+    real(c_double), intent(in) :: r
+    integer, intent(in), optional :: tag
+    real(c_double), intent(in), optional :: angle
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelOccAddCylinder = C_API(x=real(x, c_double), &
+                              y=real(y, c_double), &
+                              z=real(z, c_double), &
+                              dx=real(dx, c_double), &
+                              dy=real(dy, c_double), &
+                              dz=real(dz, c_double), &
+                              r=real(r, c_double), &
+                              tag=optval_c_int(-1, tag), &
+                              angle=optval_c_double(2*M_PI, angle), &
+                              ierr_=ierr)
+    ! Post processing
+  end function gmshModelOccAddCylinder
+
+  !> Add a cone in the OpenCASCADE CAD representation, defined by the center
+  !! (`x', `y', `z') of its first circular face, the 3 components of the vector
+  !! (`dx', `dy', `dz') defining its axis and the two radii `r1' and `r2' of the
+  !! faces (these radii can be zero). If `tag' is positive, set the tag
+  !! explicitly; otherwise a new tag is selected automatically. `angle' defines
+  !! the optional angular opening (from 0 to 2*Pi). Return the tag of the cone.
+  function gmshModelOccAddCone(x, &
+                               y, &
+                               z, &
+                               dx, &
+                               dy, &
+                               dz, &
+                               r1, &
+                               r2, &
+                               tag, &
+                               angle, &
+                               ierr)
+    interface
+    function C_API(x, &
+                   y, &
+                   z, &
+                   dx, &
+                   dy, &
+                   dz, &
+                   r1, &
+                   r2, &
+                   tag, &
+                   angle, &
+                   ierr_) &
+      bind(C, name="gmshModelOccAddCone")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      real(c_double), value, intent(in) :: x
+      real(c_double), value, intent(in) :: y
+      real(c_double), value, intent(in) :: z
+      real(c_double), value, intent(in) :: dx
+      real(c_double), value, intent(in) :: dy
+      real(c_double), value, intent(in) :: dz
+      real(c_double), value, intent(in) :: r1
+      real(c_double), value, intent(in) :: r2
+      integer(c_int), value, intent(in) :: tag
+      real(c_double), value, intent(in) :: angle
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelOccAddCone
+    real(c_double), intent(in) :: x
+    real(c_double), intent(in) :: y
+    real(c_double), intent(in) :: z
+    real(c_double), intent(in) :: dx
+    real(c_double), intent(in) :: dy
+    real(c_double), intent(in) :: dz
+    real(c_double), intent(in) :: r1
+    real(c_double), intent(in) :: r2
+    integer, intent(in), optional :: tag
+    real(c_double), intent(in), optional :: angle
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelOccAddCone = C_API(x=real(x, c_double), &
+                          y=real(y, c_double), &
+                          z=real(z, c_double), &
+                          dx=real(dx, c_double), &
+                          dy=real(dy, c_double), &
+                          dz=real(dz, c_double), &
+                          r1=real(r1, c_double), &
+                          r2=real(r2, c_double), &
+                          tag=optval_c_int(-1, tag), &
+                          angle=optval_c_double(2*M_PI, angle), &
+                          ierr_=ierr)
+    ! Post processing
+  end function gmshModelOccAddCone
+
+  !> Add a right angular wedge in the OpenCASCADE CAD representation, defined by
+  !! the right-angle point (`x', `y', `z') and the 3 extends along the x-, y-
+  !! and z-axes (`dx', `dy', `dz'). If `tag' is positive, set the tag
+  !! explicitly; otherwise a new tag is selected automatically. The optional
+  !! argument `ltx' defines the top extent along the x-axis. If a vector `zAxis'
+  !! of size 3 is provided, use it to define the z-axis. Return the tag of the
+  !! wedge.
+  function gmshModelOccAddWedge(x, &
+                                y, &
+                                z, &
+                                dx, &
+                                dy, &
+                                dz, &
+                                tag, &
+                                ltx, &
+                                zAxis, &
+                                ierr)
+    interface
+    function C_API(x, &
+                   y, &
+                   z, &
+                   dx, &
+                   dy, &
+                   dz, &
+                   tag, &
+                   ltx, &
+                   api_zAxis_, &
+                   api_zAxis_n_, &
+                   ierr_) &
+      bind(C, name="gmshModelOccAddWedge")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      real(c_double), value, intent(in) :: x
+      real(c_double), value, intent(in) :: y
+      real(c_double), value, intent(in) :: z
+      real(c_double), value, intent(in) :: dx
+      real(c_double), value, intent(in) :: dy
+      real(c_double), value, intent(in) :: dz
+      integer(c_int), value, intent(in) :: tag
+      real(c_double), value, intent(in) :: ltx
+      real(c_double), dimension(*), optional :: api_zAxis_
+      integer(c_size_t), value, intent(in) :: api_zAxis_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelOccAddWedge
+    real(c_double), intent(in) :: x
+    real(c_double), intent(in) :: y
+    real(c_double), intent(in) :: z
+    real(c_double), intent(in) :: dx
+    real(c_double), intent(in) :: dy
+    real(c_double), intent(in) :: dz
+    integer, intent(in), optional :: tag
+    real(c_double), intent(in), optional :: ltx
+    real(c_double), dimension(:), intent(in), optional :: zAxis
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelOccAddWedge = C_API(x=real(x, c_double), &
+                           y=real(y, c_double), &
+                           z=real(z, c_double), &
+                           dx=real(dx, c_double), &
+                           dy=real(dy, c_double), &
+                           dz=real(dz, c_double), &
+                           tag=optval_c_int(-1, tag), &
+                           ltx=optval_c_double(0., ltx), &
+                           api_zAxis_=zAxis, &
+                           api_zAxis_n_=size_gmsh_double(zAxis), &
+                           ierr_=ierr)
+    ! Post processing
+  end function gmshModelOccAddWedge
+
+  !> Add a torus in the OpenCASCADE CAD representation, defined by its center
+  !! (`x', `y', `z') and its 2 radii `r' and `r2'. If `tag' is positive, set the
+  !! tag explicitly; otherwise a new tag is selected automatically. The optional
+  !! argument `angle' defines the angular opening (from 0 to 2*Pi). If a vector
+  !! `zAxis' of size 3 is provided, use it to define the z-axis. Return the tag
+  !! of the torus.
+  function gmshModelOccAddTorus(x, &
+                                y, &
+                                z, &
+                                r1, &
+                                r2, &
+                                tag, &
+                                angle, &
+                                zAxis, &
+                                ierr)
+    interface
+    function C_API(x, &
+                   y, &
+                   z, &
+                   r1, &
+                   r2, &
+                   tag, &
+                   angle, &
+                   api_zAxis_, &
+                   api_zAxis_n_, &
+                   ierr_) &
+      bind(C, name="gmshModelOccAddTorus")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      real(c_double), value, intent(in) :: x
+      real(c_double), value, intent(in) :: y
+      real(c_double), value, intent(in) :: z
+      real(c_double), value, intent(in) :: r1
+      real(c_double), value, intent(in) :: r2
+      integer(c_int), value, intent(in) :: tag
+      real(c_double), value, intent(in) :: angle
+      real(c_double), dimension(*), optional :: api_zAxis_
+      integer(c_size_t), value, intent(in) :: api_zAxis_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelOccAddTorus
+    real(c_double), intent(in) :: x
+    real(c_double), intent(in) :: y
+    real(c_double), intent(in) :: z
+    real(c_double), intent(in) :: r1
+    real(c_double), intent(in) :: r2
+    integer, intent(in), optional :: tag
+    real(c_double), intent(in), optional :: angle
+    real(c_double), dimension(:), intent(in), optional :: zAxis
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelOccAddTorus = C_API(x=real(x, c_double), &
+                           y=real(y, c_double), &
+                           z=real(z, c_double), &
+                           r1=real(r1, c_double), &
+                           r2=real(r2, c_double), &
+                           tag=optval_c_int(-1, tag), &
+                           angle=optval_c_double(2*M_PI, angle), &
+                           api_zAxis_=zAxis, &
+                           api_zAxis_n_=size_gmsh_double(zAxis), &
+                           ierr_=ierr)
+    ! Post processing
+  end function gmshModelOccAddTorus
+
+  !> Add a volume (if the optional argument `makeSolid' is set) or surfaces in
+  !! the OpenCASCADE CAD representation, defined through the open or closed
+  !! wires `wireTags'. If `tag' is positive, set the tag explicitly; otherwise a
+  !! new tag is selected automatically. The new entities are returned in
+  !! `outDimTags'. If the optional argument `makeRuled' is set, the surfaces
+  !! created on the boundary are forced to be ruled surfaces. If `maxDegree' is
+  !! positive, set the maximal degree of resulting surface. The optional
+  !! argument `continuity' allows to specify the continuity of the resulting
+  !! shape ("C0", "G1", "C1", "G2", "C2", "C3", "CN"). The optional argument
+  !! `parametrization' sets the parametrization type ("ChordLength",
+  !! "Centripetal", "IsoParametric"). The optional argument `smoothing'
+  !! determines if smoothing is applied.
+  subroutine gmshModelOccAddThruSections(wireTags, &
+                                         outDimTags, &
+                                         tag, &
+                                         makeSolid, &
+                                         makeRuled, &
+                                         maxDegree, &
+                                         continuity, &
+                                         parametrization, &
+                                         smoothing, &
+                                         ierr)
+    interface
+    subroutine C_API(api_wireTags_, &
+                     api_wireTags_n_, &
+                     api_outDimTags_, &
+                     api_outDimTags_n_, &
+                     tag, &
+                     makeSolid, &
+                     makeRuled, &
+                     maxDegree, &
+                     continuity, &
+                     parametrization, &
+                     smoothing, &
+                     ierr_) &
+      bind(C, name="gmshModelOccAddThruSections")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_wireTags_
+      integer(c_size_t), value, intent(in) :: api_wireTags_n_
+      type(c_ptr), intent(out) :: api_outDimTags_
+      integer(c_size_t), intent(out) :: api_outDimTags_n_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: makeSolid
+      integer(c_int), value, intent(in) :: makeRuled
+      integer(c_int), value, intent(in) :: maxDegree
+      character(len=1, kind=c_char), dimension(*), intent(in), optional :: continuity
+      character(len=1, kind=c_char), dimension(*), intent(in), optional :: parametrization
+      integer(c_int), value, intent(in) :: smoothing
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:), intent(in) :: wireTags
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: outDimTags
+    integer, intent(in), optional :: tag
+    logical, intent(in), optional :: makeSolid
+    logical, intent(in), optional :: makeRuled
+    integer, intent(in), optional :: maxDegree
+    character(len=*), intent(in), optional :: continuity
+    character(len=*), intent(in), optional :: parametrization
+    logical, intent(in), optional :: smoothing
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_outDimTags_
+    integer(c_size_t) :: api_outDimTags_n_
+    call C_API(api_wireTags_=wireTags, &
+         api_wireTags_n_=size_gmsh_int(wireTags), &
+         api_outDimTags_=api_outDimTags_, &
+         api_outDimTags_n_=api_outDimTags_n_, &
+         tag=optval_c_int(-1, tag), &
+         makeSolid=optval_c_bool(.true., makeSolid), &
+         makeRuled=optval_c_bool(.false., makeRuled), &
+         maxDegree=optval_c_int(-1, maxDegree), &
+         continuity=istring_(optval_c_str("", continuity)), &
+         parametrization=istring_(optval_c_str("", parametrization)), &
+         smoothing=optval_c_bool(.false., smoothing), &
+         ierr_=ierr)
+    ! Post processing
+    outDimTags = ovectorpair_(api_outDimTags_, &
+      api_outDimTags_n_)
+  end subroutine gmshModelOccAddThruSections
+
+  !> Add a hollowed volume in the OpenCASCADE CAD representation, built from an
+  !! initial volume `volumeTag' and a set of faces from this volume
+  !! `excludeSurfaceTags', which are to be removed. The remaining faces of the
+  !! volume become the walls of the hollowed solid, with thickness `offset'. If
+  !! `tag' is positive, set the tag explicitly; otherwise a new tag is selected
+  !! automatically.
+  subroutine gmshModelOccAddThickSolid(volumeTag, &
+                                       excludeSurfaceTags, &
+                                       offset, &
+                                       outDimTags, &
+                                       tag, &
+                                       ierr)
+    interface
+    subroutine C_API(volumeTag, &
+                     api_excludeSurfaceTags_, &
+                     api_excludeSurfaceTags_n_, &
+                     offset, &
+                     api_outDimTags_, &
+                     api_outDimTags_n_, &
+                     tag, &
+                     ierr_) &
+      bind(C, name="gmshModelOccAddThickSolid")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: volumeTag
+      integer(c_int), dimension(*) :: api_excludeSurfaceTags_
+      integer(c_size_t), value, intent(in) :: api_excludeSurfaceTags_n_
+      real(c_double), value, intent(in) :: offset
+      type(c_ptr), intent(out) :: api_outDimTags_
+      integer(c_size_t), intent(out) :: api_outDimTags_n_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: volumeTag
+    integer(c_int), dimension(:), intent(in) :: excludeSurfaceTags
+    real(c_double), intent(in) :: offset
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: outDimTags
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_outDimTags_
+    integer(c_size_t) :: api_outDimTags_n_
+    call C_API(volumeTag=int(volumeTag, c_int), &
+         api_excludeSurfaceTags_=excludeSurfaceTags, &
+         api_excludeSurfaceTags_n_=size_gmsh_int(excludeSurfaceTags), &
+         offset=real(offset, c_double), &
+         api_outDimTags_=api_outDimTags_, &
+         api_outDimTags_n_=api_outDimTags_n_, &
+         tag=optval_c_int(-1, tag), &
+         ierr_=ierr)
+    ! Post processing
+    outDimTags = ovectorpair_(api_outDimTags_, &
+      api_outDimTags_n_)
+  end subroutine gmshModelOccAddThickSolid
+
+  !> Extrude the entities `dimTags' in the OpenCASCADE CAD representation, using
+  !! a translation along (`dx', `dy', `dz'). Return 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 (cumulative) height of the different
+  !! layers, normalized to 1. If `recombine' is set, recombine the mesh in the
+  !! layers.
+  subroutine gmshModelOccExtrude(dimTags, &
+                                 dx, &
+                                 dy, &
+                                 dz, &
+                                 outDimTags, &
+                                 numElements, &
+                                 heights, &
+                                 recombine, &
+                                 ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     dx, &
+                     dy, &
+                     dz, &
+                     api_outDimTags_, &
+                     api_outDimTags_n_, &
+                     api_numElements_, &
+                     api_numElements_n_, &
+                     api_heights_, &
+                     api_heights_n_, &
+                     recombine, &
+                     ierr_) &
+      bind(C, name="gmshModelOccExtrude")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      real(c_double), value, intent(in) :: dx
+      real(c_double), value, intent(in) :: dy
+      real(c_double), value, intent(in) :: dz
+      type(c_ptr), intent(out) :: api_outDimTags_
+      integer(c_size_t), intent(out) :: api_outDimTags_n_
+      integer(c_int), dimension(*), optional :: api_numElements_
+      integer(c_size_t), value, intent(in) :: api_numElements_n_
+      real(c_double), dimension(*), optional :: api_heights_
+      integer(c_size_t), value, intent(in) :: api_heights_n_
+      integer(c_int), value, intent(in) :: recombine
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    real(c_double), intent(in) :: dx
+    real(c_double), intent(in) :: dy
+    real(c_double), intent(in) :: dz
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: outDimTags
+    integer(c_int), dimension(:), intent(in), optional :: numElements
+    real(c_double), dimension(:), intent(in), optional :: heights
+    logical, intent(in), optional :: recombine
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_outDimTags_
+    integer(c_size_t) :: api_outDimTags_n_
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         dx=real(dx, c_double), &
+         dy=real(dy, c_double), &
+         dz=real(dz, c_double), &
+         api_outDimTags_=api_outDimTags_, &
+         api_outDimTags_n_=api_outDimTags_n_, &
+         api_numElements_=numElements, &
+         api_numElements_n_=size_gmsh_int(numElements), &
+         api_heights_=heights, &
+         api_heights_n_=size_gmsh_double(heights), &
+         recombine=optval_c_bool(.false., recombine), &
+         ierr_=ierr)
+    ! Post processing
+    outDimTags = ovectorpair_(api_outDimTags_, &
+      api_outDimTags_n_)
+  end subroutine gmshModelOccExtrude
+
+  !> Extrude the entities `dimTags' in the OpenCASCADE CAD representation, using
+  !! a rotation of `angle' radians around the axis of revolution defined by the
+  !! point (`x', `y', `z') and the direction (`ax', `ay', `az'). Return 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 (cumulative) height of the
+  !! different layers, normalized to 1. When the mesh is extruded the angle
+  !! should be strictly smaller than 2*Pi. If `recombine' is set, recombine the
+  !! mesh in the layers.
+  subroutine gmshModelOccRevolve(dimTags, &
+                                 x, &
+                                 y, &
+                                 z, &
+                                 ax, &
+                                 ay, &
+                                 az, &
+                                 angle, &
+                                 outDimTags, &
+                                 numElements, &
+                                 heights, &
+                                 recombine, &
+                                 ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     x, &
+                     y, &
+                     z, &
+                     ax, &
+                     ay, &
+                     az, &
+                     angle, &
+                     api_outDimTags_, &
+                     api_outDimTags_n_, &
+                     api_numElements_, &
+                     api_numElements_n_, &
+                     api_heights_, &
+                     api_heights_n_, &
+                     recombine, &
+                     ierr_) &
+      bind(C, name="gmshModelOccRevolve")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      real(c_double), value, intent(in) :: x
+      real(c_double), value, intent(in) :: y
+      real(c_double), value, intent(in) :: z
+      real(c_double), value, intent(in) :: ax
+      real(c_double), value, intent(in) :: ay
+      real(c_double), value, intent(in) :: az
+      real(c_double), value, intent(in) :: angle
+      type(c_ptr), intent(out) :: api_outDimTags_
+      integer(c_size_t), intent(out) :: api_outDimTags_n_
+      integer(c_int), dimension(*), optional :: api_numElements_
+      integer(c_size_t), value, intent(in) :: api_numElements_n_
+      real(c_double), dimension(*), optional :: api_heights_
+      integer(c_size_t), value, intent(in) :: api_heights_n_
+      integer(c_int), value, intent(in) :: recombine
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    real(c_double), intent(in) :: x
+    real(c_double), intent(in) :: y
+    real(c_double), intent(in) :: z
+    real(c_double), intent(in) :: ax
+    real(c_double), intent(in) :: ay
+    real(c_double), intent(in) :: az
+    real(c_double), intent(in) :: angle
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: outDimTags
+    integer(c_int), dimension(:), intent(in), optional :: numElements
+    real(c_double), dimension(:), intent(in), optional :: heights
+    logical, intent(in), optional :: recombine
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_outDimTags_
+    integer(c_size_t) :: api_outDimTags_n_
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         x=real(x, c_double), &
+         y=real(y, c_double), &
+         z=real(z, c_double), &
+         ax=real(ax, c_double), &
+         ay=real(ay, c_double), &
+         az=real(az, c_double), &
+         angle=real(angle, c_double), &
+         api_outDimTags_=api_outDimTags_, &
+         api_outDimTags_n_=api_outDimTags_n_, &
+         api_numElements_=numElements, &
+         api_numElements_n_=size_gmsh_int(numElements), &
+         api_heights_=heights, &
+         api_heights_n_=size_gmsh_double(heights), &
+         recombine=optval_c_bool(.false., recombine), &
+         ierr_=ierr)
+    ! Post processing
+    outDimTags = ovectorpair_(api_outDimTags_, &
+      api_outDimTags_n_)
+  end subroutine gmshModelOccRevolve
+
+  !> Add a pipe in the OpenCASCADE CAD representation, by extruding the entities
+  !! `dimTags' along the wire `wireTag'. The type of sweep can be specified with
+  !! `trihedron' (possible values: "DiscreteTrihedron", "CorrectedFrenet",
+  !! "Fixed", "Frenet", "ConstantNormal", "Darboux", "GuideAC", "GuidePlan",
+  !! "GuideACWithContact", "GuidePlanWithContact"). If `trihedron' is not
+  !! provided, "DiscreteTrihedron" is assumed. Return the pipe in `outDimTags'.
+  subroutine gmshModelOccAddPipe(dimTags, &
+                                 wireTag, &
+                                 outDimTags, &
+                                 trihedron, &
+                                 ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     wireTag, &
+                     api_outDimTags_, &
+                     api_outDimTags_n_, &
+                     trihedron, &
+                     ierr_) &
+      bind(C, name="gmshModelOccAddPipe")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      integer(c_int), value, intent(in) :: wireTag
+      type(c_ptr), intent(out) :: api_outDimTags_
+      integer(c_size_t), intent(out) :: api_outDimTags_n_
+      character(len=1, kind=c_char), dimension(*), intent(in), optional :: trihedron
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    integer, intent(in) :: wireTag
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: outDimTags
+    character(len=*), intent(in), optional :: trihedron
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_outDimTags_
+    integer(c_size_t) :: api_outDimTags_n_
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         wireTag=int(wireTag, c_int), &
+         api_outDimTags_=api_outDimTags_, &
+         api_outDimTags_n_=api_outDimTags_n_, &
+         trihedron=istring_(optval_c_str("", trihedron)), &
+         ierr_=ierr)
+    ! Post processing
+    outDimTags = ovectorpair_(api_outDimTags_, &
+      api_outDimTags_n_)
+  end subroutine gmshModelOccAddPipe
+
+  !> Fillet the volumes `volumeTags' on the curves `curveTags' with radii
+  !! `radii'. The `radii' vector can either contain a single radius, as many
+  !! radii as `curveTags', or twice as many as `curveTags' (in which case
+  !! different radii are provided for the begin and end points of the curves).
+  !! Return the filleted entities in `outDimTags'. Remove the original volume if
+  !! `removeVolume' is set.
+  subroutine gmshModelOccFillet(volumeTags, &
+                                curveTags, &
+                                radii, &
+                                outDimTags, &
+                                removeVolume, &
+                                ierr)
+    interface
+    subroutine C_API(api_volumeTags_, &
+                     api_volumeTags_n_, &
+                     api_curveTags_, &
+                     api_curveTags_n_, &
+                     api_radii_, &
+                     api_radii_n_, &
+                     api_outDimTags_, &
+                     api_outDimTags_n_, &
+                     removeVolume, &
+                     ierr_) &
+      bind(C, name="gmshModelOccFillet")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_volumeTags_
+      integer(c_size_t), value, intent(in) :: api_volumeTags_n_
+      integer(c_int), dimension(*) :: api_curveTags_
+      integer(c_size_t), value, intent(in) :: api_curveTags_n_
+      real(c_double), dimension(*) :: api_radii_
+      integer(c_size_t), value, intent(in) :: api_radii_n_
+      type(c_ptr), intent(out) :: api_outDimTags_
+      integer(c_size_t), intent(out) :: api_outDimTags_n_
+      integer(c_int), value, intent(in) :: removeVolume
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:), intent(in) :: volumeTags
+    integer(c_int), dimension(:), intent(in) :: curveTags
+    real(c_double), dimension(:), intent(in) :: radii
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: outDimTags
+    logical, intent(in), optional :: removeVolume
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_outDimTags_
+    integer(c_size_t) :: api_outDimTags_n_
+    call C_API(api_volumeTags_=volumeTags, &
+         api_volumeTags_n_=size_gmsh_int(volumeTags), &
+         api_curveTags_=curveTags, &
+         api_curveTags_n_=size_gmsh_int(curveTags), &
+         api_radii_=radii, &
+         api_radii_n_=size_gmsh_double(radii), &
+         api_outDimTags_=api_outDimTags_, &
+         api_outDimTags_n_=api_outDimTags_n_, &
+         removeVolume=optval_c_bool(.true., removeVolume), &
+         ierr_=ierr)
+    ! Post processing
+    outDimTags = ovectorpair_(api_outDimTags_, &
+      api_outDimTags_n_)
+  end subroutine gmshModelOccFillet
+
+  !> Chamfer the volumes `volumeTags' on the curves `curveTags' with distances
+  !! `distances' measured on surfaces `surfaceTags'. The `distances' vector can
+  !! either contain a single distance, as many distances as `curveTags' and
+  !! `surfaceTags', or twice as many as `curveTags' and `surfaceTags' (in which
+  !! case the first in each pair is measured on the corresponding surface in
+  !! `surfaceTags', the other on the other adjacent surface). Return the
+  !! chamfered entities in `outDimTags'. Remove the original volume if
+  !! `removeVolume' is set.
+  subroutine gmshModelOccChamfer(volumeTags, &
+                                 curveTags, &
+                                 surfaceTags, &
+                                 distances, &
+                                 outDimTags, &
+                                 removeVolume, &
+                                 ierr)
+    interface
+    subroutine C_API(api_volumeTags_, &
+                     api_volumeTags_n_, &
+                     api_curveTags_, &
+                     api_curveTags_n_, &
+                     api_surfaceTags_, &
+                     api_surfaceTags_n_, &
+                     api_distances_, &
+                     api_distances_n_, &
+                     api_outDimTags_, &
+                     api_outDimTags_n_, &
+                     removeVolume, &
+                     ierr_) &
+      bind(C, name="gmshModelOccChamfer")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_volumeTags_
+      integer(c_size_t), value, intent(in) :: api_volumeTags_n_
+      integer(c_int), dimension(*) :: api_curveTags_
+      integer(c_size_t), value, intent(in) :: api_curveTags_n_
+      integer(c_int), dimension(*) :: api_surfaceTags_
+      integer(c_size_t), value, intent(in) :: api_surfaceTags_n_
+      real(c_double), dimension(*) :: api_distances_
+      integer(c_size_t), value, intent(in) :: api_distances_n_
+      type(c_ptr), intent(out) :: api_outDimTags_
+      integer(c_size_t), intent(out) :: api_outDimTags_n_
+      integer(c_int), value, intent(in) :: removeVolume
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:), intent(in) :: volumeTags
+    integer(c_int), dimension(:), intent(in) :: curveTags
+    integer(c_int), dimension(:), intent(in) :: surfaceTags
+    real(c_double), dimension(:), intent(in) :: distances
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: outDimTags
+    logical, intent(in), optional :: removeVolume
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_outDimTags_
+    integer(c_size_t) :: api_outDimTags_n_
+    call C_API(api_volumeTags_=volumeTags, &
+         api_volumeTags_n_=size_gmsh_int(volumeTags), &
+         api_curveTags_=curveTags, &
+         api_curveTags_n_=size_gmsh_int(curveTags), &
+         api_surfaceTags_=surfaceTags, &
+         api_surfaceTags_n_=size_gmsh_int(surfaceTags), &
+         api_distances_=distances, &
+         api_distances_n_=size_gmsh_double(distances), &
+         api_outDimTags_=api_outDimTags_, &
+         api_outDimTags_n_=api_outDimTags_n_, &
+         removeVolume=optval_c_bool(.true., removeVolume), &
+         ierr_=ierr)
+    ! Post processing
+    outDimTags = ovectorpair_(api_outDimTags_, &
+      api_outDimTags_n_)
+  end subroutine gmshModelOccChamfer
+
+  !> Compute the boolean union (the fusion) of the entities `objectDimTags' and
+  !! `toolDimTags' in the OpenCASCADE CAD representation. Return the resulting
+  !! entities in `outDimTags'. If `tag' is positive, try to set the tag
+  !! explicitly (only valid if the boolean operation results in a single
+  !! entity). Remove the object if `removeObject' is set. Remove the tool if
+  !! `removeTool' is set.
+  subroutine gmshModelOccFuse(objectDimTags, &
+                              toolDimTags, &
+                              outDimTags, &
+                              outDimTagsMap, &
+                              outDimTagsMap_n, &
+                              tag, &
+                              removeObject, &
+                              removeTool, &
+                              ierr)
+    interface
+    subroutine C_API(api_objectDimTags_, &
+                     api_objectDimTags_n_, &
+                     api_toolDimTags_, &
+                     api_toolDimTags_n_, &
+                     api_outDimTags_, &
+                     api_outDimTags_n_, &
+                     api_outDimTagsMap_, &
+                     api_outDimTagsMap_n_, &
+                     api_outDimTagsMap_nn_, &
+                     tag, &
+                     removeObject, &
+                     removeTool, &
+                     ierr_) &
+      bind(C, name="gmshModelOccFuse")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_objectDimTags_
+      integer(c_size_t), value, intent(in) :: api_objectDimTags_n_
+      integer(c_int), dimension(*) :: api_toolDimTags_
+      integer(c_size_t), value, intent(in) :: api_toolDimTags_n_
+      type(c_ptr), intent(out) :: api_outDimTags_
+      integer(c_size_t), intent(out) :: api_outDimTags_n_
+      type(c_ptr), intent(out) :: api_outDimTagsMap_
+      type(c_ptr), intent(out) :: api_outDimTagsMap_n_
+      integer(c_size_t) :: api_outDimTagsMap_nn_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: removeObject
+      integer(c_int), value, intent(in) :: removeTool
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: objectDimTags
+    integer(c_int), dimension(:,:), intent(in) :: toolDimTags
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: outDimTags
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: outDimTagsMap
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: outDimTagsMap_n
+    integer, intent(in), optional :: tag
+    logical, intent(in), optional :: removeObject
+    logical, intent(in), optional :: removeTool
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_outDimTags_
+    integer(c_size_t) :: api_outDimTags_n_
+    type(c_ptr) :: api_outDimTagsMap_, api_outDimTagsMap_n_
+    integer(c_size_t) :: api_outDimTagsMap_nn_
+    call C_API(api_objectDimTags_=objectDimTags, &
+         api_objectDimTags_n_=size_gmsh_pair(objectDimTags), &
+         api_toolDimTags_=toolDimTags, &
+         api_toolDimTags_n_=size_gmsh_pair(toolDimTags), &
+         api_outDimTags_=api_outDimTags_, &
+         api_outDimTags_n_=api_outDimTags_n_, &
+         api_outDimTagsMap_=api_outDimTagsMap_, &
+         api_outDimTagsMap_n_=api_outDimTagsMap_n_, &
+         api_outDimTagsMap_nn_=api_outDimTagsMap_nn_, &
+         tag=optval_c_int(-1, tag), &
+         removeObject=optval_c_bool(.true., removeObject), &
+         removeTool=optval_c_bool(.true., removeTool), &
+         ierr_=ierr)
+    ! Post processing
+    outDimTags = ovectorpair_(api_outDimTags_, &
+      api_outDimTags_n_)
+    call ovectorvectorpair_(api_outDimTagsMap_, &
+      api_outDimTagsMap_n_, &
+      api_outDimTagsMap_nn_, &
+      outDimTagsMap, &
+      outDimTagsMap_n)
+  end subroutine gmshModelOccFuse
+
+  !> Compute the boolean intersection (the common parts) of the entities
+  !! `objectDimTags' and `toolDimTags' in the OpenCASCADE CAD representation.
+  !! Return the resulting entities in `outDimTags'. If `tag' is positive, try to
+  !! set the tag explicitly (only valid if the boolean operation results in a
+  !! single entity). Remove the object if `removeObject' is set. Remove the tool
+  !! if `removeTool' is set.
+  subroutine gmshModelOccIntersect(objectDimTags, &
+                                   toolDimTags, &
+                                   outDimTags, &
+                                   outDimTagsMap, &
+                                   outDimTagsMap_n, &
+                                   tag, &
+                                   removeObject, &
+                                   removeTool, &
+                                   ierr)
+    interface
+    subroutine C_API(api_objectDimTags_, &
+                     api_objectDimTags_n_, &
+                     api_toolDimTags_, &
+                     api_toolDimTags_n_, &
+                     api_outDimTags_, &
+                     api_outDimTags_n_, &
+                     api_outDimTagsMap_, &
+                     api_outDimTagsMap_n_, &
+                     api_outDimTagsMap_nn_, &
+                     tag, &
+                     removeObject, &
+                     removeTool, &
+                     ierr_) &
+      bind(C, name="gmshModelOccIntersect")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_objectDimTags_
+      integer(c_size_t), value, intent(in) :: api_objectDimTags_n_
+      integer(c_int), dimension(*) :: api_toolDimTags_
+      integer(c_size_t), value, intent(in) :: api_toolDimTags_n_
+      type(c_ptr), intent(out) :: api_outDimTags_
+      integer(c_size_t), intent(out) :: api_outDimTags_n_
+      type(c_ptr), intent(out) :: api_outDimTagsMap_
+      type(c_ptr), intent(out) :: api_outDimTagsMap_n_
+      integer(c_size_t) :: api_outDimTagsMap_nn_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: removeObject
+      integer(c_int), value, intent(in) :: removeTool
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: objectDimTags
+    integer(c_int), dimension(:,:), intent(in) :: toolDimTags
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: outDimTags
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: outDimTagsMap
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: outDimTagsMap_n
+    integer, intent(in), optional :: tag
+    logical, intent(in), optional :: removeObject
+    logical, intent(in), optional :: removeTool
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_outDimTags_
+    integer(c_size_t) :: api_outDimTags_n_
+    type(c_ptr) :: api_outDimTagsMap_, api_outDimTagsMap_n_
+    integer(c_size_t) :: api_outDimTagsMap_nn_
+    call C_API(api_objectDimTags_=objectDimTags, &
+         api_objectDimTags_n_=size_gmsh_pair(objectDimTags), &
+         api_toolDimTags_=toolDimTags, &
+         api_toolDimTags_n_=size_gmsh_pair(toolDimTags), &
+         api_outDimTags_=api_outDimTags_, &
+         api_outDimTags_n_=api_outDimTags_n_, &
+         api_outDimTagsMap_=api_outDimTagsMap_, &
+         api_outDimTagsMap_n_=api_outDimTagsMap_n_, &
+         api_outDimTagsMap_nn_=api_outDimTagsMap_nn_, &
+         tag=optval_c_int(-1, tag), &
+         removeObject=optval_c_bool(.true., removeObject), &
+         removeTool=optval_c_bool(.true., removeTool), &
+         ierr_=ierr)
+    ! Post processing
+    outDimTags = ovectorpair_(api_outDimTags_, &
+      api_outDimTags_n_)
+    call ovectorvectorpair_(api_outDimTagsMap_, &
+      api_outDimTagsMap_n_, &
+      api_outDimTagsMap_nn_, &
+      outDimTagsMap, &
+      outDimTagsMap_n)
+  end subroutine gmshModelOccIntersect
+
+  !> Compute the boolean difference between the entities `objectDimTags' and
+  !! `toolDimTags' in the OpenCASCADE CAD representation. Return the resulting
+  !! entities in `outDimTags'. If `tag' is positive, try to set the tag
+  !! explicitly (only valid if the boolean operation results in a single
+  !! entity). Remove the object if `removeObject' is set. Remove the tool if
+  !! `removeTool' is set.
+  subroutine gmshModelOccCut(objectDimTags, &
+                             toolDimTags, &
+                             outDimTags, &
+                             outDimTagsMap, &
+                             outDimTagsMap_n, &
+                             tag, &
+                             removeObject, &
+                             removeTool, &
+                             ierr)
+    interface
+    subroutine C_API(api_objectDimTags_, &
+                     api_objectDimTags_n_, &
+                     api_toolDimTags_, &
+                     api_toolDimTags_n_, &
+                     api_outDimTags_, &
+                     api_outDimTags_n_, &
+                     api_outDimTagsMap_, &
+                     api_outDimTagsMap_n_, &
+                     api_outDimTagsMap_nn_, &
+                     tag, &
+                     removeObject, &
+                     removeTool, &
+                     ierr_) &
+      bind(C, name="gmshModelOccCut")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_objectDimTags_
+      integer(c_size_t), value, intent(in) :: api_objectDimTags_n_
+      integer(c_int), dimension(*) :: api_toolDimTags_
+      integer(c_size_t), value, intent(in) :: api_toolDimTags_n_
+      type(c_ptr), intent(out) :: api_outDimTags_
+      integer(c_size_t), intent(out) :: api_outDimTags_n_
+      type(c_ptr), intent(out) :: api_outDimTagsMap_
+      type(c_ptr), intent(out) :: api_outDimTagsMap_n_
+      integer(c_size_t) :: api_outDimTagsMap_nn_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: removeObject
+      integer(c_int), value, intent(in) :: removeTool
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: objectDimTags
+    integer(c_int), dimension(:,:), intent(in) :: toolDimTags
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: outDimTags
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: outDimTagsMap
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: outDimTagsMap_n
+    integer, intent(in), optional :: tag
+    logical, intent(in), optional :: removeObject
+    logical, intent(in), optional :: removeTool
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_outDimTags_
+    integer(c_size_t) :: api_outDimTags_n_
+    type(c_ptr) :: api_outDimTagsMap_, api_outDimTagsMap_n_
+    integer(c_size_t) :: api_outDimTagsMap_nn_
+    call C_API(api_objectDimTags_=objectDimTags, &
+         api_objectDimTags_n_=size_gmsh_pair(objectDimTags), &
+         api_toolDimTags_=toolDimTags, &
+         api_toolDimTags_n_=size_gmsh_pair(toolDimTags), &
+         api_outDimTags_=api_outDimTags_, &
+         api_outDimTags_n_=api_outDimTags_n_, &
+         api_outDimTagsMap_=api_outDimTagsMap_, &
+         api_outDimTagsMap_n_=api_outDimTagsMap_n_, &
+         api_outDimTagsMap_nn_=api_outDimTagsMap_nn_, &
+         tag=optval_c_int(-1, tag), &
+         removeObject=optval_c_bool(.true., removeObject), &
+         removeTool=optval_c_bool(.true., removeTool), &
+         ierr_=ierr)
+    ! Post processing
+    outDimTags = ovectorpair_(api_outDimTags_, &
+      api_outDimTags_n_)
+    call ovectorvectorpair_(api_outDimTagsMap_, &
+      api_outDimTagsMap_n_, &
+      api_outDimTagsMap_nn_, &
+      outDimTagsMap, &
+      outDimTagsMap_n)
+  end subroutine gmshModelOccCut
+
+  !> Compute the boolean fragments (general fuse) resulting from the
+  !! intersection of the entities `objectDimTags' and `toolDimTags' in the
+  !! OpenCASCADE CAD representation, making all iterfaces conformal. When
+  !! applied to entities of different dimensions, the lower dimensional entities
+  !! will be automatically embedded in the higher dimensional entities if they
+  !! are not on their boundary. Return the resulting entities in `outDimTags'.
+  !! If `tag' is positive, try to set the tag explicitly (only valid if the
+  !! boolean operation results in a single entity). Remove the object if
+  !! `removeObject' is set. Remove the tool if `removeTool' is set.
+  subroutine gmshModelOccFragment(objectDimTags, &
+                                  toolDimTags, &
+                                  outDimTags, &
+                                  outDimTagsMap, &
+                                  outDimTagsMap_n, &
+                                  tag, &
+                                  removeObject, &
+                                  removeTool, &
+                                  ierr)
+    interface
+    subroutine C_API(api_objectDimTags_, &
+                     api_objectDimTags_n_, &
+                     api_toolDimTags_, &
+                     api_toolDimTags_n_, &
+                     api_outDimTags_, &
+                     api_outDimTags_n_, &
+                     api_outDimTagsMap_, &
+                     api_outDimTagsMap_n_, &
+                     api_outDimTagsMap_nn_, &
+                     tag, &
+                     removeObject, &
+                     removeTool, &
+                     ierr_) &
+      bind(C, name="gmshModelOccFragment")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_objectDimTags_
+      integer(c_size_t), value, intent(in) :: api_objectDimTags_n_
+      integer(c_int), dimension(*) :: api_toolDimTags_
+      integer(c_size_t), value, intent(in) :: api_toolDimTags_n_
+      type(c_ptr), intent(out) :: api_outDimTags_
+      integer(c_size_t), intent(out) :: api_outDimTags_n_
+      type(c_ptr), intent(out) :: api_outDimTagsMap_
+      type(c_ptr), intent(out) :: api_outDimTagsMap_n_
+      integer(c_size_t) :: api_outDimTagsMap_nn_
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: removeObject
+      integer(c_int), value, intent(in) :: removeTool
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: objectDimTags
+    integer(c_int), dimension(:,:), intent(in) :: toolDimTags
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: outDimTags
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: outDimTagsMap
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: outDimTagsMap_n
+    integer, intent(in), optional :: tag
+    logical, intent(in), optional :: removeObject
+    logical, intent(in), optional :: removeTool
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_outDimTags_
+    integer(c_size_t) :: api_outDimTags_n_
+    type(c_ptr) :: api_outDimTagsMap_, api_outDimTagsMap_n_
+    integer(c_size_t) :: api_outDimTagsMap_nn_
+    call C_API(api_objectDimTags_=objectDimTags, &
+         api_objectDimTags_n_=size_gmsh_pair(objectDimTags), &
+         api_toolDimTags_=toolDimTags, &
+         api_toolDimTags_n_=size_gmsh_pair(toolDimTags), &
+         api_outDimTags_=api_outDimTags_, &
+         api_outDimTags_n_=api_outDimTags_n_, &
+         api_outDimTagsMap_=api_outDimTagsMap_, &
+         api_outDimTagsMap_n_=api_outDimTagsMap_n_, &
+         api_outDimTagsMap_nn_=api_outDimTagsMap_nn_, &
+         tag=optval_c_int(-1, tag), &
+         removeObject=optval_c_bool(.true., removeObject), &
+         removeTool=optval_c_bool(.true., removeTool), &
+         ierr_=ierr)
+    ! Post processing
+    outDimTags = ovectorpair_(api_outDimTags_, &
+      api_outDimTags_n_)
+    call ovectorvectorpair_(api_outDimTagsMap_, &
+      api_outDimTagsMap_n_, &
+      api_outDimTagsMap_nn_, &
+      outDimTagsMap, &
+      outDimTagsMap_n)
+  end subroutine gmshModelOccFragment
+
+  !> Translate the entities `dimTags' in the OpenCASCADE CAD representation
+  !! along (`dx', `dy', `dz').
+  subroutine gmshModelOccTranslate(dimTags, &
+                                   dx, &
+                                   dy, &
+                                   dz, &
+                                   ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     dx, &
+                     dy, &
+                     dz, &
+                     ierr_) &
+      bind(C, name="gmshModelOccTranslate")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      real(c_double), value, intent(in) :: dx
+      real(c_double), value, intent(in) :: dy
+      real(c_double), value, intent(in) :: dz
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    real(c_double), intent(in) :: dx
+    real(c_double), intent(in) :: dy
+    real(c_double), intent(in) :: dz
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         dx=real(dx, c_double), &
+         dy=real(dy, c_double), &
+         dz=real(dz, c_double), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelOccTranslate
+
+  !> Rotate the entities `dimTags' in the OpenCASCADE CAD representation by
+  !! `angle' radians around the axis of revolution defined by the point (`x',
+  !! `y', `z') and the direction (`ax', `ay', `az').
+  subroutine gmshModelOccRotate(dimTags, &
+                                x, &
+                                y, &
+                                z, &
+                                ax, &
+                                ay, &
+                                az, &
+                                angle, &
+                                ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     x, &
+                     y, &
+                     z, &
+                     ax, &
+                     ay, &
+                     az, &
+                     angle, &
+                     ierr_) &
+      bind(C, name="gmshModelOccRotate")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      real(c_double), value, intent(in) :: x
+      real(c_double), value, intent(in) :: y
+      real(c_double), value, intent(in) :: z
+      real(c_double), value, intent(in) :: ax
+      real(c_double), value, intent(in) :: ay
+      real(c_double), value, intent(in) :: az
+      real(c_double), value, intent(in) :: angle
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    real(c_double), intent(in) :: x
+    real(c_double), intent(in) :: y
+    real(c_double), intent(in) :: z
+    real(c_double), intent(in) :: ax
+    real(c_double), intent(in) :: ay
+    real(c_double), intent(in) :: az
+    real(c_double), intent(in) :: angle
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         x=real(x, c_double), &
+         y=real(y, c_double), &
+         z=real(z, c_double), &
+         ax=real(ax, c_double), &
+         ay=real(ay, c_double), &
+         az=real(az, c_double), &
+         angle=real(angle, c_double), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelOccRotate
+
+  !> Scale the entities `dimTags' in the OpenCASCADE CAD representation by
+  !! factors `a', `b' and `c' along the three coordinate axes; use (`x', `y',
+  !! `z') as the center of the homothetic transformation.
+  subroutine gmshModelOccDilate(dimTags, &
+                                x, &
+                                y, &
+                                z, &
+                                a, &
+                                b, &
+                                c, &
+                                ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     x, &
+                     y, &
+                     z, &
+                     a, &
+                     b, &
+                     c, &
+                     ierr_) &
+      bind(C, name="gmshModelOccDilate")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      real(c_double), value, intent(in) :: x
+      real(c_double), value, intent(in) :: y
+      real(c_double), value, intent(in) :: z
+      real(c_double), value, intent(in) :: a
+      real(c_double), value, intent(in) :: b
+      real(c_double), value, intent(in) :: c
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    real(c_double), intent(in) :: x
+    real(c_double), intent(in) :: y
+    real(c_double), intent(in) :: z
+    real(c_double), intent(in) :: a
+    real(c_double), intent(in) :: b
+    real(c_double), intent(in) :: c
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         x=real(x, c_double), &
+         y=real(y, c_double), &
+         z=real(z, c_double), &
+         a=real(a, c_double), &
+         b=real(b, c_double), &
+         c=real(c, c_double), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelOccDilate
+
+  !> Mirror the entities `dimTags' in the OpenCASCADE CAD representation, with
+  !! respect to the plane of equation `a' * x + `b' * y + `c' * z + `d' = 0.
+  subroutine gmshModelOccMirror(dimTags, &
+                                a, &
+                                b, &
+                                c, &
+                                d, &
+                                ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     a, &
+                     b, &
+                     c, &
+                     d, &
+                     ierr_) &
+      bind(C, name="gmshModelOccMirror")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      real(c_double), value, intent(in) :: a
+      real(c_double), value, intent(in) :: b
+      real(c_double), value, intent(in) :: c
+      real(c_double), value, intent(in) :: d
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    real(c_double), intent(in) :: a
+    real(c_double), intent(in) :: b
+    real(c_double), intent(in) :: c
+    real(c_double), intent(in) :: d
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         a=real(a, c_double), &
+         b=real(b, c_double), &
+         c=real(c, c_double), &
+         d=real(d, c_double), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelOccMirror
+
+  !> Mirror the entities `dimTags' in the OpenCASCADE CAD representation, with
+  !! respect to the plane of equation `a' * x + `b' * y + `c' * z + `d' = 0.
+  !! (This is a deprecated synonym for `mirror'.)
+  subroutine gmshModelOccSymmetrize(dimTags, &
+                                    a, &
+                                    b, &
+                                    c, &
+                                    d, &
+                                    ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     a, &
+                     b, &
+                     c, &
+                     d, &
+                     ierr_) &
+      bind(C, name="gmshModelOccSymmetrize")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      real(c_double), value, intent(in) :: a
+      real(c_double), value, intent(in) :: b
+      real(c_double), value, intent(in) :: c
+      real(c_double), value, intent(in) :: d
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    real(c_double), intent(in) :: a
+    real(c_double), intent(in) :: b
+    real(c_double), intent(in) :: c
+    real(c_double), intent(in) :: d
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         a=real(a, c_double), &
+         b=real(b, c_double), &
+         c=real(c, c_double), &
+         d=real(d, c_double), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelOccSymmetrize
+
+  !> Apply a general affine transformation matrix `affineTransform' (16 entries
+  !! of a 4x4 matrix, by row; only the 12 first can be provided for convenience)
+  !! to the entities `dimTags' in the OpenCASCADE CAD representation.
+  subroutine gmshModelOccAffineTransform(dimTags, &
+                                         affineTransform, &
+                                         ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     api_affineTransform_, &
+                     api_affineTransform_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelOccAffineTransform")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      real(c_double), dimension(*) :: api_affineTransform_
+      integer(c_size_t), value, intent(in) :: api_affineTransform_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    real(c_double), dimension(:), intent(in) :: affineTransform
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         api_affineTransform_=affineTransform, &
+         api_affineTransform_n_=size_gmsh_double(affineTransform), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelOccAffineTransform
+
+  !> Copy the entities `dimTags' in the OpenCASCADE CAD representation; the new
+  !! entities are returned in `outDimTags'.
+  subroutine gmshModelOccCopy(dimTags, &
+                              outDimTags, &
+                              ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     api_outDimTags_, &
+                     api_outDimTags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelOccCopy")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      type(c_ptr), intent(out) :: api_outDimTags_
+      integer(c_size_t), intent(out) :: api_outDimTags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: outDimTags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_outDimTags_
+    integer(c_size_t) :: api_outDimTags_n_
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         api_outDimTags_=api_outDimTags_, &
+         api_outDimTags_n_=api_outDimTags_n_, &
+         ierr_=ierr)
+    ! Post processing
+    outDimTags = ovectorpair_(api_outDimTags_, &
+      api_outDimTags_n_)
+  end subroutine gmshModelOccCopy
+
+  !> Remove the entities `dimTags' in the OpenCASCADE CAD representation,
+  !! provided that they are not on the boundary of higher-dimensional entities.
+  !! If `recursive' is true, remove all the entities on their boundaries, down
+  !! to dimension 0.
+  subroutine gmshModelOccRemove(dimTags, &
+                                recursive, &
+                                ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     recursive, &
+                     ierr_) &
+      bind(C, name="gmshModelOccRemove")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      integer(c_int), value, intent(in) :: recursive
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    logical, intent(in), optional :: recursive
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         recursive=optval_c_bool(.false., recursive), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelOccRemove
+
+  !> Remove all duplicate entities in the OpenCASCADE CAD representation
+  !! (different entities at the same geometrical location) after intersecting
+  !! (using boolean fragments) all highest dimensional entities.
+  subroutine gmshModelOccRemoveAllDuplicates(ierr)
+    interface
+    subroutine C_API(ierr_) &
+      bind(C, name="gmshModelOccRemoveAllDuplicates")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelOccRemoveAllDuplicates
+
+  !> Apply various healing procedures to the entities `dimTags' (or to all the
+  !! entities in the model if `dimTags' is empty) in the OpenCASCADE CAD
+  !! representation. Return the healed entities in `outDimTags'.
+  subroutine gmshModelOccHealShapes(outDimTags, &
+                                    dimTags, &
+                                    tolerance, &
+                                    fixDegenerated, &
+                                    fixSmallEdges, &
+                                    fixSmallFaces, &
+                                    sewFaces, &
+                                    makeSolids, &
+                                    ierr)
+    interface
+    subroutine C_API(api_outDimTags_, &
+                     api_outDimTags_n_, &
+                     api_dimTags_, &
+                     api_dimTags_n_, &
+                     tolerance, &
+                     fixDegenerated, &
+                     fixSmallEdges, &
+                     fixSmallFaces, &
+                     sewFaces, &
+                     makeSolids, &
+                     ierr_) &
+      bind(C, name="gmshModelOccHealShapes")
+      use, intrinsic :: iso_c_binding
+      type(c_ptr), intent(out) :: api_outDimTags_
+      integer(c_size_t), intent(out) :: api_outDimTags_n_
+      integer(c_int), dimension(*), optional :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      real(c_double), value, intent(in) :: tolerance
+      integer(c_int), value, intent(in) :: fixDegenerated
+      integer(c_int), value, intent(in) :: fixSmallEdges
+      integer(c_int), value, intent(in) :: fixSmallFaces
+      integer(c_int), value, intent(in) :: sewFaces
+      integer(c_int), value, intent(in) :: makeSolids
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: outDimTags
+    integer(c_int), dimension(:,:), intent(in), optional :: dimTags
+    real(c_double), intent(in), optional :: tolerance
+    logical, intent(in), optional :: fixDegenerated
+    logical, intent(in), optional :: fixSmallEdges
+    logical, intent(in), optional :: fixSmallFaces
+    logical, intent(in), optional :: sewFaces
+    logical, intent(in), optional :: makeSolids
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_outDimTags_
+    integer(c_size_t) :: api_outDimTags_n_
+    call C_API(api_outDimTags_=api_outDimTags_, &
+         api_outDimTags_n_=api_outDimTags_n_, &
+         api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         tolerance=optval_c_double(1e-8, tolerance), &
+         fixDegenerated=optval_c_bool(.true., fixDegenerated), &
+         fixSmallEdges=optval_c_bool(.true., fixSmallEdges), &
+         fixSmallFaces=optval_c_bool(.true., fixSmallFaces), &
+         sewFaces=optval_c_bool(.true., sewFaces), &
+         makeSolids=optval_c_bool(.true., makeSolids), &
+         ierr_=ierr)
+    ! Post processing
+    outDimTags = ovectorpair_(api_outDimTags_, &
+      api_outDimTags_n_)
+  end subroutine gmshModelOccHealShapes
+
+  !> Convert the entities `dimTags' to NURBS.
+  subroutine gmshModelOccConvertToNURBS(dimTags, &
+                                        ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelOccConvertToNURBS")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelOccConvertToNURBS
+
+  !> Import BREP, STEP or IGES shapes from the file `fileName' in the
+  !! OpenCASCADE CAD representation. The imported entities are returned in
+  !! `outDimTags'. If the optional argument `highestDimOnly' is set, only import
+  !! the highest dimensional entities in the file. The optional argument
+  !! `format' can be used to force the format of the file (currently "brep",
+  !! "step" or "iges").
+  subroutine gmshModelOccImportShapes(fileName, &
+                                      outDimTags, &
+                                      highestDimOnly, &
+                                      format, &
+                                      ierr)
+    interface
+    subroutine C_API(fileName, &
+                     api_outDimTags_, &
+                     api_outDimTags_n_, &
+                     highestDimOnly, &
+                     format, &
+                     ierr_) &
+      bind(C, name="gmshModelOccImportShapes")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: fileName
+      type(c_ptr), intent(out) :: api_outDimTags_
+      integer(c_size_t), intent(out) :: api_outDimTags_n_
+      integer(c_int), value, intent(in) :: highestDimOnly
+      character(len=1, kind=c_char), dimension(*), intent(in), optional :: format
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: fileName
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: outDimTags
+    logical, intent(in), optional :: highestDimOnly
+    character(len=*), intent(in), optional :: format
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_outDimTags_
+    integer(c_size_t) :: api_outDimTags_n_
+    call C_API(fileName=istring_(fileName), &
+         api_outDimTags_=api_outDimTags_, &
+         api_outDimTags_n_=api_outDimTags_n_, &
+         highestDimOnly=optval_c_bool(.true., highestDimOnly), &
+         format=istring_(optval_c_str("", format)), &
+         ierr_=ierr)
+    ! Post processing
+    outDimTags = ovectorpair_(api_outDimTags_, &
+      api_outDimTags_n_)
+  end subroutine gmshModelOccImportShapes
+
+  !> Imports an OpenCASCADE `shape' by providing a pointer to a native
+  !! OpenCASCADE `TopoDS_Shape' object (passed as a pointer to void). The
+  !! imported entities are returned in `outDimTags'. If the optional argument
+  !! `highestDimOnly' is set, only import the highest dimensional entities in
+  !! `shape'. In Python, this function can be used for integration with
+  !! PythonOCC, in which the SwigPyObject pointer of `TopoDS_Shape' must be
+  !! passed as an int to `shape', i.e., `shape = int(pythonocc_shape.this)'.
+  !! Warning: this function is unsafe, as providing an invalid pointer will lead
+  !! to undefined behavior.
+  subroutine gmshModelOccImportShapesNativePointer(shape, &
+                                                   outDimTags, &
+                                                   highestDimOnly, &
+                                                   ierr)
+    interface
+    subroutine C_API(shape, &
+                     api_outDimTags_, &
+                     api_outDimTags_n_, &
+                     highestDimOnly, &
+                     ierr_) &
+      bind(C, name="gmshModelOccImportShapesNativePointer")
+      use, intrinsic :: iso_c_binding
+      type(c_ptr), value, intent(in) :: shape
+      type(c_ptr), intent(out) :: api_outDimTags_
+      integer(c_size_t), intent(out) :: api_outDimTags_n_
+      integer(c_int), value, intent(in) :: highestDimOnly
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    type(c_ptr), intent(in) :: shape
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: outDimTags
+    logical, intent(in), optional :: highestDimOnly
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_outDimTags_
+    integer(c_size_t) :: api_outDimTags_n_
+    call C_API(shape=shape, &
+         api_outDimTags_=api_outDimTags_, &
+         api_outDimTags_n_=api_outDimTags_n_, &
+         highestDimOnly=optval_c_bool(.true., highestDimOnly), &
+         ierr_=ierr)
+    ! Post processing
+    outDimTags = ovectorpair_(api_outDimTags_, &
+      api_outDimTags_n_)
+  end subroutine gmshModelOccImportShapesNativePointer
+
+  !> Get all the OpenCASCADE entities. If `dim' is >= 0, return 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.
+  subroutine gmshModelOccGetEntities(dimTags, &
+                                     dim, &
+                                     ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     dim, &
+                     ierr_) &
+      bind(C, name="gmshModelOccGetEntities")
+      use, intrinsic :: iso_c_binding
+      type(c_ptr), intent(out) :: api_dimTags_
+      integer(c_size_t), intent(out) :: api_dimTags_n_
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: dimTags
+    integer, intent(in), optional :: dim
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_dimTags_
+    integer(c_size_t) :: api_dimTags_n_
+    call C_API(api_dimTags_=api_dimTags_, &
+         api_dimTags_n_=api_dimTags_n_, &
+         dim=optval_c_int(-1, dim), &
+         ierr_=ierr)
+    ! Post processing
+    dimTags = ovectorpair_(api_dimTags_, &
+      api_dimTags_n_)
+  end subroutine gmshModelOccGetEntities
+
+  !> Get the OpenCASCADE entities in the bounding box defined by the two points
+  !! (`xmin', `ymin', `zmin') and (`xmax', `ymax', `zmax'). If `dim' is >= 0,
+  !! return only the entities of the specified dimension (e.g. points if `dim'
+  !! == 0).
+  subroutine gmshModelOccGetEntitiesInBoundingBox(xmin, &
+                                                  ymin, &
+                                                  zmin, &
+                                                  xmax, &
+                                                  ymax, &
+                                                  zmax, &
+                                                  tags, &
+                                                  dim, &
+                                                  ierr)
+    interface
+    subroutine C_API(xmin, &
+                     ymin, &
+                     zmin, &
+                     xmax, &
+                     ymax, &
+                     zmax, &
+                     api_tags_, &
+                     api_tags_n_, &
+                     dim, &
+                     ierr_) &
+      bind(C, name="gmshModelOccGetEntitiesInBoundingBox")
+      use, intrinsic :: iso_c_binding
+      real(c_double), value, intent(in) :: xmin
+      real(c_double), value, intent(in) :: ymin
+      real(c_double), value, intent(in) :: zmin
+      real(c_double), value, intent(in) :: xmax
+      real(c_double), value, intent(in) :: ymax
+      real(c_double), value, intent(in) :: zmax
+      type(c_ptr), intent(out) :: api_tags_
+      integer(c_size_t), intent(out) :: api_tags_n_
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    real(c_double), intent(in) :: xmin
+    real(c_double), intent(in) :: ymin
+    real(c_double), intent(in) :: zmin
+    real(c_double), intent(in) :: xmax
+    real(c_double), intent(in) :: ymax
+    real(c_double), intent(in) :: zmax
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: tags
+    integer, intent(in), optional :: dim
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_tags_
+    integer(c_size_t) :: api_tags_n_
+    call C_API(xmin=real(xmin, c_double), &
+         ymin=real(ymin, c_double), &
+         zmin=real(zmin, c_double), &
+         xmax=real(xmax, c_double), &
+         ymax=real(ymax, c_double), &
+         zmax=real(zmax, c_double), &
+         api_tags_=api_tags_, &
+         api_tags_n_=api_tags_n_, &
+         dim=optval_c_int(-1, dim), &
+         ierr_=ierr)
+    ! Post processing
+    tags = ovectorpair_(api_tags_, &
+      api_tags_n_)
+  end subroutine gmshModelOccGetEntitiesInBoundingBox
+
+  !> Get the bounding box (`xmin', `ymin', `zmin'), (`xmax', `ymax', `zmax') of
+  !! the OpenCASCADE entity of dimension `dim' and tag `tag'.
+  subroutine gmshModelOccGetBoundingBox(dim, &
+                                        tag, &
+                                        xmin, &
+                                        ymin, &
+                                        zmin, &
+                                        xmax, &
+                                        ymax, &
+                                        zmax, &
+                                        ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     xmin, &
+                     ymin, &
+                     zmin, &
+                     xmax, &
+                     ymax, &
+                     zmax, &
+                     ierr_) &
+      bind(C, name="gmshModelOccGetBoundingBox")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      real(c_double) :: xmin
+      real(c_double) :: ymin
+      real(c_double) :: zmin
+      real(c_double) :: xmax
+      real(c_double) :: ymax
+      real(c_double) :: zmax
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    real(c_double) :: xmin
+    real(c_double) :: ymin
+    real(c_double) :: zmin
+    real(c_double) :: xmax
+    real(c_double) :: ymax
+    real(c_double) :: zmax
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         xmin=xmin, &
+         ymin=ymin, &
+         zmin=zmin, &
+         xmax=xmax, &
+         ymax=ymax, &
+         zmax=zmax, &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelOccGetBoundingBox
+
+  !> Get the tags `curveLoopTags' of the curve loops making up the surface of
+  !! tag `surfaceTag', as well as the tags `curveTags' of the curves making up
+  !! each curve loop.
+  subroutine gmshModelOccGetCurveLoops(surfaceTag, &
+                                       curveLoopTags, &
+                                       curveTags, &
+                                       curveTags_n, &
+                                       ierr)
+    interface
+    subroutine C_API(surfaceTag, &
+                     api_curveLoopTags_, &
+                     api_curveLoopTags_n_, &
+                     api_curveTags_, &
+                     api_curveTags_n_, &
+                     api_curveTags_nn_, &
+                     ierr_) &
+      bind(C, name="gmshModelOccGetCurveLoops")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: surfaceTag
+      type(c_ptr), intent(out) :: api_curveLoopTags_
+      integer(c_size_t), intent(out) :: api_curveLoopTags_n_
+      type(c_ptr), intent(out) :: api_curveTags_
+      type(c_ptr), intent(out) :: api_curveTags_n_
+      integer(c_size_t), intent(out) :: api_curveTags_nn_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: surfaceTag
+    integer(c_int), dimension(:), allocatable, intent(out) :: curveLoopTags
+    integer(c_int), dimension(:), allocatable, intent(out) :: curveTags
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: curveTags_n
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_curveLoopTags_
+    integer(c_size_t) :: api_curveLoopTags_n_
+    type(c_ptr) :: api_curveTags_, api_curveTags_n_
+    integer(c_size_t) :: api_curveTags_nn_
+    call C_API(surfaceTag=int(surfaceTag, c_int), &
+         api_curveLoopTags_=api_curveLoopTags_, &
+         api_curveLoopTags_n_=api_curveLoopTags_n_, &
+         api_curveTags_=api_curveTags_, &
+         api_curveTags_n_=api_curveTags_n_, &
+         api_curveTags_nn_=api_curveTags_nn_, &
+         ierr_=ierr)
+    ! Post processing
+    curveLoopTags = ovectorint_(api_curveLoopTags_, &
+      api_curveLoopTags_n_)
+    call ovectorvectorint_(api_curveTags_, &
+      api_curveTags_n_, &
+      api_curveTags_nn_, &
+      curveTags, &
+      curveTags_n)
+  end subroutine gmshModelOccGetCurveLoops
+
+  !> Get the tags `surfaceLoopTags' of the surface loops making up the volume of
+  !! tag `volumeTag', as well as the tags `surfaceTags' of the surfaces making
+  !! up each surface loop.
+  subroutine gmshModelOccGetSurfaceLoops(volumeTag, &
+                                         surfaceLoopTags, &
+                                         surfaceTags, &
+                                         surfaceTags_n, &
+                                         ierr)
+    interface
+    subroutine C_API(volumeTag, &
+                     api_surfaceLoopTags_, &
+                     api_surfaceLoopTags_n_, &
+                     api_surfaceTags_, &
+                     api_surfaceTags_n_, &
+                     api_surfaceTags_nn_, &
+                     ierr_) &
+      bind(C, name="gmshModelOccGetSurfaceLoops")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: volumeTag
+      type(c_ptr), intent(out) :: api_surfaceLoopTags_
+      integer(c_size_t), intent(out) :: api_surfaceLoopTags_n_
+      type(c_ptr), intent(out) :: api_surfaceTags_
+      type(c_ptr), intent(out) :: api_surfaceTags_n_
+      integer(c_size_t), intent(out) :: api_surfaceTags_nn_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: volumeTag
+    integer(c_int), dimension(:), allocatable, intent(out) :: surfaceLoopTags
+    integer(c_int), dimension(:), allocatable, intent(out) :: surfaceTags
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: surfaceTags_n
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_surfaceLoopTags_
+    integer(c_size_t) :: api_surfaceLoopTags_n_
+    type(c_ptr) :: api_surfaceTags_, api_surfaceTags_n_
+    integer(c_size_t) :: api_surfaceTags_nn_
+    call C_API(volumeTag=int(volumeTag, c_int), &
+         api_surfaceLoopTags_=api_surfaceLoopTags_, &
+         api_surfaceLoopTags_n_=api_surfaceLoopTags_n_, &
+         api_surfaceTags_=api_surfaceTags_, &
+         api_surfaceTags_n_=api_surfaceTags_n_, &
+         api_surfaceTags_nn_=api_surfaceTags_nn_, &
+         ierr_=ierr)
+    ! Post processing
+    surfaceLoopTags = ovectorint_(api_surfaceLoopTags_, &
+      api_surfaceLoopTags_n_)
+    call ovectorvectorint_(api_surfaceTags_, &
+      api_surfaceTags_n_, &
+      api_surfaceTags_nn_, &
+      surfaceTags, &
+      surfaceTags_n)
+  end subroutine gmshModelOccGetSurfaceLoops
+
+  !> Get the mass of the OpenCASCADE entity of dimension `dim' and tag `tag'.
+  subroutine gmshModelOccGetMass(dim, &
+                                 tag, &
+                                 mass, &
+                                 ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     mass, &
+                     ierr_) &
+      bind(C, name="gmshModelOccGetMass")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      real(c_double) :: mass
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    real(c_double) :: mass
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         mass=mass, &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelOccGetMass
+
+  !> Get the center of mass of the OpenCASCADE entity of dimension `dim' and tag
+  !! `tag'.
+  subroutine gmshModelOccGetCenterOfMass(dim, &
+                                         tag, &
+                                         x, &
+                                         y, &
+                                         z, &
+                                         ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     x, &
+                     y, &
+                     z, &
+                     ierr_) &
+      bind(C, name="gmshModelOccGetCenterOfMass")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      real(c_double) :: x
+      real(c_double) :: y
+      real(c_double) :: z
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    real(c_double) :: x
+    real(c_double) :: y
+    real(c_double) :: z
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         x=x, &
+         y=y, &
+         z=z, &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelOccGetCenterOfMass
+
+  !> Get the matrix of inertia (by row) of the OpenCASCADE entity of dimension
+  !! `dim' and tag `tag'.
+  subroutine gmshModelOccGetMatrixOfInertia(dim, &
+                                            tag, &
+                                            mat, &
+                                            ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     api_mat_, &
+                     api_mat_n_, &
+                     ierr_) &
+      bind(C, name="gmshModelOccGetMatrixOfInertia")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      type(c_ptr), intent(out) :: api_mat_
+      integer(c_size_t) :: api_mat_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    real(c_double), dimension(:), allocatable, intent(out) :: mat
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_mat_
+    integer(c_size_t) :: api_mat_n_
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         api_mat_=api_mat_, &
+         api_mat_n_=api_mat_n_, &
+         ierr_=ierr)
+    ! Post processing
+    mat = ovectordouble_(api_mat_, &
+      api_mat_n_)
+  end subroutine gmshModelOccGetMatrixOfInertia
+
+  !> Get the maximum tag of entities of dimension `dim' in the OpenCASCADE CAD
+  !! representation.
+  function gmshModelOccGetMaxTag(dim, &
+                                 ierr)
+    interface
+    function C_API(dim, &
+                   ierr_) &
+      bind(C, name="gmshModelOccGetMaxTag")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshModelOccGetMaxTag
+    integer, intent(in) :: dim
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshModelOccGetMaxTag = C_API(dim=int(dim, c_int), &
+                            ierr_=ierr)
+    ! Post processing
+  end function gmshModelOccGetMaxTag
+
+  !> Set the maximum tag `maxTag' for entities of dimension `dim' in the
+  !! OpenCASCADE CAD representation.
+  subroutine gmshModelOccSetMaxTag(dim, &
+                                   maxTag, &
+                                   ierr)
+    interface
+    subroutine C_API(dim, &
+                     maxTag, &
+                     ierr_) &
+      bind(C, name="gmshModelOccSetMaxTag")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: maxTag
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: maxTag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=int(dim, c_int), &
+         maxTag=int(maxTag, c_int), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelOccSetMaxTag
+
+  !> Synchronize the 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. Without synchronization the entities in the OpenCASCADE CAD
+  !! representation are not available to any function outside of the OpenCASCADE
+  !! CAD kernel functions.
+  subroutine gmshModelOccSynchronize(ierr)
+    interface
+    subroutine C_API(ierr_) &
+      bind(C, name="gmshModelOccSynchronize")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelOccSynchronize
+
+  !> Set a mesh size constraint on the entities `dimTags' in the OpenCASCADE CAD
+  !! representation. Currently only entities of dimension 0 (points) are
+  !! handled.
+  subroutine gmshModelOccMeshSetSize(dimTags, &
+                                     size, &
+                                     ierr)
+    interface
+    subroutine C_API(api_dimTags_, &
+                     api_dimTags_n_, &
+                     size, &
+                     ierr_) &
+      bind(C, name="gmshModelOccMeshSetSize")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), dimension(*) :: api_dimTags_
+      integer(c_size_t), value, intent(in) :: api_dimTags_n_
+      real(c_double), value, intent(in) :: size
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:,:), intent(in) :: dimTags
+    real(c_double), intent(in) :: size
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_dimTags_=dimTags, &
+         api_dimTags_n_=size_gmsh_pair(dimTags), &
+         size=real(size, c_double), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshModelOccMeshSetSize
+
+  !> Add 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. Return the view tag.
+  function gmshViewAdd(name, &
+                       tag, &
+                       ierr)
+    interface
+    function C_API(name, &
+                   tag, &
+                   ierr_) &
+      bind(C, name="gmshViewAdd")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshViewAdd
+    character(len=*), intent(in) :: name
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshViewAdd = C_API(name=istring_(name), &
+                  tag=optval_c_int(-1, tag), &
+                  ierr_=ierr)
+    ! Post processing
+  end function gmshViewAdd
+
+  !> Remove the view with tag `tag'.
+  subroutine gmshViewRemove(tag, &
+                            ierr)
+    interface
+    subroutine C_API(tag, &
+                     ierr_) &
+      bind(C, name="gmshViewRemove")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(tag=int(tag, c_int), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshViewRemove
+
+  !> Get 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.
+  function gmshViewGetIndex(tag, &
+                            ierr)
+    interface
+    function C_API(tag, &
+                   ierr_) &
+      bind(C, name="gmshViewGetIndex")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshViewGetIndex
+    integer, intent(in) :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshViewGetIndex = C_API(tag=int(tag, c_int), &
+                       ierr_=ierr)
+    ! Post processing
+  end function gmshViewGetIndex
+
+  !> Get the tags of all views.
+  subroutine gmshViewGetTags(tags, &
+                             ierr)
+    interface
+    subroutine C_API(api_tags_, &
+                     api_tags_n_, &
+                     ierr_) &
+      bind(C, name="gmshViewGetTags")
+      use, intrinsic :: iso_c_binding
+      type(c_ptr), intent(out) :: api_tags_
+      integer(c_size_t), intent(out) :: api_tags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), dimension(:), allocatable, intent(out) :: tags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_tags_
+    integer(c_size_t) :: api_tags_n_
+    call C_API(api_tags_=api_tags_, &
+         api_tags_n_=api_tags_n_, &
+         ierr_=ierr)
+    ! Post processing
+    tags = ovectorint_(api_tags_, &
+      api_tags_n_)
+  end subroutine gmshViewGetTags
+
+  !> Add 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". `step' specifies the identifier (>= 0) of the data in a
+  !! sequence. `tags' gives the tags of the nodes or elements in the mesh to
+  !! which the data is associated. `data' is a vector of the same length as
+  !! `tags': each entry is the vector of double precision numbers representing
+  !! the data associated with the corresponding tag. The optional `time'
+  !! argument associate a 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 one to specify data in several sub-sets.
+  subroutine gmshViewAddModelData(tag, &
+                                  step, &
+                                  modelName, &
+                                  dataType, &
+                                  tags, &
+                                  data, &
+                                  data_n, &
+                                  time, &
+                                  numComponents, &
+                                  partition, &
+                                  ierr)
+    interface
+    subroutine C_API(tag, &
+                     step, &
+                     modelName, &
+                     dataType, &
+                     api_tags_, &
+                     api_tags_n_, &
+                     api_data_, &
+                     api_data_n_, &
+                     api_data_nn_, &
+                     time, &
+                     numComponents, &
+                     partition, &
+                     ierr_) &
+      bind(C, name="gmshViewAddModelData")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: step
+      character(len=1, kind=c_char), dimension(*), intent(in) :: modelName
+      character(len=1, kind=c_char), dimension(*), intent(in) :: dataType
+      integer(c_size_t), dimension(*) :: api_tags_
+      integer(c_size_t), value, intent(in) :: api_tags_n_
+      type(c_ptr), intent(in) :: api_data_
+      type(c_ptr), intent(in) :: api_data_n_
+      integer(c_size_t), value, intent(in) :: api_data_nn_
+      real(c_double), value, intent(in) :: time
+      integer(c_int), value, intent(in) :: numComponents
+      integer(c_int), value, intent(in) :: partition
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    integer, intent(in) :: step
+    character(len=*), intent(in) :: modelName
+    character(len=*), intent(in) :: dataType
+    integer(c_size_t), dimension(:), intent(in) :: tags
+    real(c_double), dimension(:), intent(in) :: data
+    integer(c_size_t), dimension(:), intent(in) :: data_n
+    real(c_double), intent(in), optional :: time
+    integer, intent(in), optional :: numComponents
+    integer, intent(in), optional :: partition
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_data_
+    type(c_ptr) :: api_data_n_
+    integer(c_size_t) :: api_data_nn_
+    call ivectorvectordouble_(data, &
+      data_n, &
+      api_data_, &
+      api_data_n_, &
+      api_data_nn_)
+    call C_API(tag=int(tag, c_int), &
+         step=int(step, c_int), &
+         modelName=istring_(modelName), &
+         dataType=istring_(dataType), &
+         api_tags_=tags, &
+         api_tags_n_=size_gmsh_size(tags), &
+         api_data_=api_data_, &
+         api_data_n_=api_data_n_, &
+         api_data_nn_=api_data_nn_, &
+         time=optval_c_double(0., time), &
+         numComponents=optval_c_int(-1, numComponents), &
+         partition=optval_c_int(0, partition), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshViewAddModelData
+
+  !> Add homogeneous model-based post-processing data to the view with tag
+  !! `tag'. The arguments have the same meaning as in `addModelData', except
+  !! that `data' is supposed to be homogeneous and is thus flattened in a single
+  !! vector. For data types that can lead to different data sizes per tag (like
+  !! "ElementNodeData"), the data should be padded.
+  subroutine gmshViewAddHomogeneousModelData(tag, &
+                                             step, &
+                                             modelName, &
+                                             dataType, &
+                                             tags, &
+                                             data, &
+                                             time, &
+                                             numComponents, &
+                                             partition, &
+                                             ierr)
+    interface
+    subroutine C_API(tag, &
+                     step, &
+                     modelName, &
+                     dataType, &
+                     api_tags_, &
+                     api_tags_n_, &
+                     api_data_, &
+                     api_data_n_, &
+                     time, &
+                     numComponents, &
+                     partition, &
+                     ierr_) &
+      bind(C, name="gmshViewAddHomogeneousModelData")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: step
+      character(len=1, kind=c_char), dimension(*), intent(in) :: modelName
+      character(len=1, kind=c_char), dimension(*), intent(in) :: dataType
+      integer(c_size_t), dimension(*) :: api_tags_
+      integer(c_size_t), value, intent(in) :: api_tags_n_
+      real(c_double), dimension(*) :: api_data_
+      integer(c_size_t), value, intent(in) :: api_data_n_
+      real(c_double), value, intent(in) :: time
+      integer(c_int), value, intent(in) :: numComponents
+      integer(c_int), value, intent(in) :: partition
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    integer, intent(in) :: step
+    character(len=*), intent(in) :: modelName
+    character(len=*), intent(in) :: dataType
+    integer(c_size_t), dimension(:), intent(in) :: tags
+    real(c_double), dimension(:), intent(in) :: data
+    real(c_double), intent(in), optional :: time
+    integer, intent(in), optional :: numComponents
+    integer, intent(in), optional :: partition
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(tag=int(tag, c_int), &
+         step=int(step, c_int), &
+         modelName=istring_(modelName), &
+         dataType=istring_(dataType), &
+         api_tags_=tags, &
+         api_tags_n_=size_gmsh_size(tags), &
+         api_data_=data, &
+         api_data_n_=size_gmsh_double(data), &
+         time=optval_c_double(0., time), &
+         numComponents=optval_c_int(-1, numComponents), &
+         partition=optval_c_int(0, partition), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshViewAddHomogeneousModelData
+
+  !> Get model-based post-processing data from the view with tag `tag' at step
+  !! `step'. Return the `data' associated to the nodes or the elements with tags
+  !! `tags', as well as the `dataType' and the number of components
+  !! `numComponents'.
+  subroutine gmshViewGetModelData(tag, &
+                                  step, &
+                                  dataType, &
+                                  tags, &
+                                  data, &
+                                  data_n, &
+                                  time, &
+                                  numComponents, &
+                                  ierr)
+    interface
+    subroutine C_API(tag, &
+                     step, &
+                     api_dataType_, &
+                     api_tags_, &
+                     api_tags_n_, &
+                     api_data_, &
+                     api_data_n_, &
+                     api_data_nn_, &
+                     time, &
+                     numComponents, &
+                     ierr_) &
+      bind(C, name="gmshViewGetModelData")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: step
+      character(kind=c_char), dimension(*) :: api_dataType_
+      type(c_ptr), intent(out) :: api_tags_
+      integer(c_size_t), intent(out) :: api_tags_n_
+      type(c_ptr), intent(out) :: api_data_
+      type(c_ptr), intent(out) :: api_data_n_
+      integer(c_size_t), intent(out) :: api_data_nn_
+      real(c_double) :: time
+      integer(c_int) :: numComponents
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    integer, intent(in) :: step
+    character(len=:), allocatable, intent(out) :: dataType
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: tags
+    real(c_double), dimension(:), allocatable, intent(out) :: data
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: data_n
+    real(c_double) :: time
+    integer(c_int) :: numComponents
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_tags_
+    integer(c_size_t) :: api_tags_n_
+    type(c_ptr) :: api_data_, api_data_n_
+    integer(c_size_t) :: api_data_nn_
+    call C_API(tag=int(tag, c_int), &
+         step=int(step, c_int), &
+         api_dataType_=dataType, &
+         api_tags_=api_tags_, &
+         api_tags_n_=api_tags_n_, &
+         api_data_=api_data_, &
+         api_data_n_=api_data_n_, &
+         api_data_nn_=api_data_nn_, &
+         time=time, &
+         numComponents=numComponents, &
+         ierr_=ierr)
+    ! Post processing
+    tags = ovectorsize_(api_tags_, &
+      api_tags_n_)
+    call ovectorvectordouble_(api_data_, &
+      api_data_n_, &
+      api_data_nn_, &
+      data, &
+      data_n)
+  end subroutine gmshViewGetModelData
+
+  !> Get homogeneous model-based post-processing data from the view with tag
+  !! `tag' at step `step'. The arguments have the same meaning as in
+  !! `getModelData', except that `data' is returned flattened in a single
+  !! vector, with the appropriate padding if necessary.
+  subroutine gmshViewGetHomogeneousModelData(tag, &
+                                             step, &
+                                             dataType, &
+                                             tags, &
+                                             data, &
+                                             time, &
+                                             numComponents, &
+                                             ierr)
+    interface
+    subroutine C_API(tag, &
+                     step, &
+                     api_dataType_, &
+                     api_tags_, &
+                     api_tags_n_, &
+                     api_data_, &
+                     api_data_n_, &
+                     time, &
+                     numComponents, &
+                     ierr_) &
+      bind(C, name="gmshViewGetHomogeneousModelData")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: step
+      character(kind=c_char), dimension(*) :: api_dataType_
+      type(c_ptr), intent(out) :: api_tags_
+      integer(c_size_t), intent(out) :: api_tags_n_
+      type(c_ptr), intent(out) :: api_data_
+      integer(c_size_t) :: api_data_n_
+      real(c_double) :: time
+      integer(c_int) :: numComponents
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    integer, intent(in) :: step
+    character(len=:), allocatable, intent(out) :: dataType
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: tags
+    real(c_double), dimension(:), allocatable, intent(out) :: data
+    real(c_double) :: time
+    integer(c_int) :: numComponents
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_tags_
+    integer(c_size_t) :: api_tags_n_
+    type(c_ptr) :: api_data_
+    integer(c_size_t) :: api_data_n_
+    call C_API(tag=int(tag, c_int), &
+         step=int(step, c_int), &
+         api_dataType_=dataType, &
+         api_tags_=api_tags_, &
+         api_tags_n_=api_tags_n_, &
+         api_data_=api_data_, &
+         api_data_n_=api_data_n_, &
+         time=time, &
+         numComponents=numComponents, &
+         ierr_=ierr)
+    ! Post processing
+    tags = ovectorsize_(api_tags_, &
+      api_tags_n_)
+    data = ovectordouble_(api_data_, &
+      api_data_n_)
+  end subroutine gmshViewGetHomogeneousModelData
+
+  !> Add list-based post-processing data to the view with tag `tag'. List-based
+  !! datasets are independent from any model and any mesh. `dataType' identifies
+  !! the data by concatenating the field type ("S" for scalar, "V" for vector,
+  !! "T" for tensor) and the element type ("P" for point, "L" for line, "T" for
+  !! triangle, "S" for tetrahedron, "I" for prism, "H" for hexaHedron, "Y" for
+  !! pyramid). For example `dataType' should be "ST" for a scalar field on
+  !! triangles. `numEle' gives the number of elements in the data. `data'
+  !! contains the data for the `numEle' elements, concatenated, with node
+  !! coordinates followed by values per node, repeated for each step: [e1x1,
+  !! ..., e1xn, e1y1, ..., e1yn, e1z1, ..., e1zn, e1v1..., e1vN, e2x1, ...].
+  subroutine gmshViewAddListData(tag, &
+                                 dataType, &
+                                 numEle, &
+                                 data, &
+                                 ierr)
+    interface
+    subroutine C_API(tag, &
+                     dataType, &
+                     numEle, &
+                     api_data_, &
+                     api_data_n_, &
+                     ierr_) &
+      bind(C, name="gmshViewAddListData")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      character(len=1, kind=c_char), dimension(*), intent(in) :: dataType
+      integer(c_int), value, intent(in) :: numEle
+      real(c_double), dimension(*) :: api_data_
+      integer(c_size_t), value, intent(in) :: api_data_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    character(len=*), intent(in) :: dataType
+    integer, intent(in) :: numEle
+    real(c_double), dimension(:), intent(in) :: data
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(tag=int(tag, c_int), &
+         dataType=istring_(dataType), &
+         numEle=int(numEle, c_int), &
+         api_data_=data, &
+         api_data_n_=size_gmsh_double(data), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshViewAddListData
+
+  !> Get list-based post-processing data from the view with tag `tag'. Return
+  !! the types `dataTypes', the number of elements `numElements' for each data
+  !! type and the `data' for each data type.
+  subroutine gmshViewGetListData(tag, &
+                                 dataType, &
+                                 numElements, &
+                                 data, &
+                                 data_n, &
+                                 ierr)
+    interface
+    subroutine C_API(tag, &
+                     api_dataType_, &
+                     api_dataType_n_, &
+                     api_numElements_, &
+                     api_numElements_n_, &
+                     api_data_, &
+                     api_data_n_, &
+                     api_data_nn_, &
+                     ierr_) &
+      bind(C, name="gmshViewGetListData")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      type(c_ptr), intent(out) :: api_dataType_
+      integer(c_size_t), intent(out) :: api_dataType_n_
+      type(c_ptr), intent(out) :: api_numElements_
+      integer(c_size_t), intent(out) :: api_numElements_n_
+      type(c_ptr), intent(out) :: api_data_
+      type(c_ptr), intent(out) :: api_data_n_
+      integer(c_size_t), intent(out) :: api_data_nn_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    character(len=GMSH_API_MAX_STR_LEN), dimension(:), allocatable, intent(out) :: dataType
+    integer(c_int), dimension(:), allocatable, intent(out) :: numElements
+    real(c_double), dimension(:), allocatable, intent(out) :: data
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: data_n
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_dataType_
+    integer(c_size_t) :: api_dataType_n_
+    type(c_ptr) :: api_numElements_
+    integer(c_size_t) :: api_numElements_n_
+    type(c_ptr) :: api_data_, api_data_n_
+    integer(c_size_t) :: api_data_nn_
+    call C_API(tag=int(tag, c_int), &
+         api_dataType_=api_dataType_, &
+         api_dataType_n_=api_dataType_n_, &
+         api_numElements_=api_numElements_, &
+         api_numElements_n_=api_numElements_n_, &
+         api_data_=api_data_, &
+         api_data_n_=api_data_n_, &
+         api_data_nn_=api_data_nn_, &
+         ierr_=ierr)
+    ! Post processing
+    dataType = ovectorstring_(api_dataType_, &
+      api_dataType_n_)
+    numElements = ovectorint_(api_numElements_, &
+      api_numElements_n_)
+    call ovectorvectordouble_(api_data_, &
+      api_data_n_, &
+      api_data_nn_, &
+      data, &
+      data_n)
+  end subroutine gmshViewGetListData
+
+  !> Add a string to a list-based post-processing view with tag `tag'. If
+  !! `coord' contains 3 coordinates the string is positioned in the 3D model
+  !! space ("3D string"); if it contains 2 coordinates it is positioned in the
+  !! 2D graphics viewport ("2D string"). `data' contains one or more (for
+  !! multistep views) strings. `style' contains key-value pairs of styling
+  !! parameters, concatenated. Available keys are "Font" (possible values:
+  !! "Times-Roman", "Times-Bold", "Times-Italic", "Times-BoldItalic",
+  !! "Helvetica", "Helvetica-Bold", "Helvetica-Oblique", "Helvetica-
+  !! BoldOblique", "Courier", "Courier-Bold", "Courier-Oblique", "Courier-
+  !! BoldOblique", "Symbol", "ZapfDingbats", "Screen"), "FontSize" and "Align"
+  !! (possible values: "Left" or "BottomLeft", "Center" or "BottomCenter",
+  !! "Right" or "BottomRight", "TopLeft", "TopCenter", "TopRight", "CenterLeft",
+  !! "CenterCenter", "CenterRight").
+  subroutine gmshViewAddListDataString(tag, &
+                                       coord, &
+                                       data, &
+                                       style, &
+                                       ierr)
+    interface
+    subroutine C_API(tag, &
+                     api_coord_, &
+                     api_coord_n_, &
+                     api_data_, &
+                     api_data_n_, &
+                     api_style_, &
+                     api_style_n_, &
+                     ierr_) &
+      bind(C, name="gmshViewAddListDataString")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      real(c_double), dimension(*) :: api_coord_
+      integer(c_size_t), value, intent(in) :: api_coord_n_
+      type(c_ptr), dimension(*) :: api_data_
+      integer(c_size_t), value, intent(in) :: api_data_n_
+      type(c_ptr), dimension(*), optional :: api_style_
+      integer(c_size_t), value, intent(in) :: api_style_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    real(c_double), dimension(:), intent(in) :: coord
+    character(len=*), dimension(:), intent(in) :: data
+    character(len=*), dimension(:), intent(in), optional :: style
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    character(len=GMSH_API_MAX_STR_LEN, kind=c_char), allocatable :: api_data_strs(:)
+    type(c_ptr), allocatable :: api_data_(:)
+    character(len=GMSH_API_MAX_STR_LEN, kind=c_char), allocatable :: api_style_strs(:)
+    type(c_ptr), allocatable :: api_style_(:)
+    call ivectorstring_(data, &
+      api_data_strs, &
+      api_data_)
+    call ivectorstring_(style, &
+      api_style_strs, &
+      api_style_)
+    call C_API(tag=int(tag, c_int), &
+         api_coord_=coord, &
+         api_coord_n_=size_gmsh_double(coord), &
+         api_data_=api_data_, &
+         api_data_n_=size_gmsh_str(data), &
+         api_style_=api_style_, &
+         api_style_n_=size_gmsh_str(style), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshViewAddListDataString
+
+  !> Get list-based post-processing data strings (2D strings if `dim' = 2, 3D
+  !! strings if `dim' = 3) from the view with tag `tag'. Return the coordinates
+  !! in `coord', the strings in `data' and the styles in `style'.
+  subroutine gmshViewGetListDataStrings(tag, &
+                                        dim, &
+                                        coord, &
+                                        data, &
+                                        style, &
+                                        ierr)
+    interface
+    subroutine C_API(tag, &
+                     dim, &
+                     api_coord_, &
+                     api_coord_n_, &
+                     api_data_, &
+                     api_data_n_, &
+                     api_style_, &
+                     api_style_n_, &
+                     ierr_) &
+      bind(C, name="gmshViewGetListDataStrings")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: dim
+      type(c_ptr), intent(out) :: api_coord_
+      integer(c_size_t) :: api_coord_n_
+      type(c_ptr), intent(out) :: api_data_
+      integer(c_size_t), intent(out) :: api_data_n_
+      type(c_ptr), intent(out) :: api_style_
+      integer(c_size_t), intent(out) :: api_style_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    integer, intent(in) :: dim
+    real(c_double), dimension(:), allocatable, intent(out) :: coord
+    character(len=GMSH_API_MAX_STR_LEN), dimension(:), allocatable, intent(out) :: data
+    character(len=GMSH_API_MAX_STR_LEN), dimension(:), allocatable, intent(out) :: style
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_coord_
+    integer(c_size_t) :: api_coord_n_
+    type(c_ptr) :: api_data_
+    integer(c_size_t) :: api_data_n_
+    type(c_ptr) :: api_style_
+    integer(c_size_t) :: api_style_n_
+    call C_API(tag=int(tag, c_int), &
+         dim=int(dim, c_int), &
+         api_coord_=api_coord_, &
+         api_coord_n_=api_coord_n_, &
+         api_data_=api_data_, &
+         api_data_n_=api_data_n_, &
+         api_style_=api_style_, &
+         api_style_n_=api_style_n_, &
+         ierr_=ierr)
+    ! Post processing
+    coord = ovectordouble_(api_coord_, &
+      api_coord_n_)
+    data = ovectorstring_(api_data_, &
+      api_data_n_)
+    style = ovectorstring_(api_style_, &
+      api_style_n_)
+  end subroutine gmshViewGetListDataStrings
+
+  !> Set interpolation matrices for the element family `type' ("Line",
+  !! "Triangle", "Quadrangle", "Tetrahedron", "Hexahedron", "Prism", "Pyramid")
+  !! in the view `tag'. The approximation of the values over an element is
+  !! written as a linear combination of `d' basis functions f_i(u, v, w) =
+  !! sum_(j = 0, ..., `d' - 1) `coef'[i][j] u^`exp'[j][0] v^`exp'[j][1]
+  !! w^`exp'[j][2], i = 0, ..., `d'-1, with u, v, w the coordinates in the
+  !! reference element. The `coef' matrix (of size `d' x `d') and the `exp'
+  !! matrix (of size `d' x 3) are stored as vectors, by row. If `dGeo' is
+  !! positive, use `coefGeo' and `expGeo' to define the interpolation of the x,
+  !! y, z coordinates of the element in terms of the u, v, w coordinates, in
+  !! exactly the same way. If `d' < 0, remove the interpolation matrices.
+  subroutine gmshViewSetInterpolationMatrices(tag, &
+                                              type, &
+                                              d, &
+                                              coef, &
+                                              exp, &
+                                              dGeo, &
+                                              coefGeo, &
+                                              expGeo, &
+                                              ierr)
+    interface
+    subroutine C_API(tag, &
+                     type, &
+                     d, &
+                     api_coef_, &
+                     api_coef_n_, &
+                     api_exp_, &
+                     api_exp_n_, &
+                     dGeo, &
+                     api_coefGeo_, &
+                     api_coefGeo_n_, &
+                     api_expGeo_, &
+                     api_expGeo_n_, &
+                     ierr_) &
+      bind(C, name="gmshViewSetInterpolationMatrices")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      character(len=1, kind=c_char), dimension(*), intent(in) :: type
+      integer(c_int), value, intent(in) :: d
+      real(c_double), dimension(*) :: api_coef_
+      integer(c_size_t), value, intent(in) :: api_coef_n_
+      real(c_double), dimension(*) :: api_exp_
+      integer(c_size_t), value, intent(in) :: api_exp_n_
+      integer(c_int), value, intent(in) :: dGeo
+      real(c_double), dimension(*), optional :: api_coefGeo_
+      integer(c_size_t), value, intent(in) :: api_coefGeo_n_
+      real(c_double), dimension(*), optional :: api_expGeo_
+      integer(c_size_t), value, intent(in) :: api_expGeo_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    character(len=*), intent(in) :: type
+    integer, intent(in) :: d
+    real(c_double), dimension(:), intent(in) :: coef
+    real(c_double), dimension(:), intent(in) :: exp
+    integer, intent(in), optional :: dGeo
+    real(c_double), dimension(:), intent(in), optional :: coefGeo
+    real(c_double), dimension(:), intent(in), optional :: expGeo
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(tag=int(tag, c_int), &
+         type=istring_(type), &
+         d=int(d, c_int), &
+         api_coef_=coef, &
+         api_coef_n_=size_gmsh_double(coef), &
+         api_exp_=exp, &
+         api_exp_n_=size_gmsh_double(exp), &
+         dGeo=optval_c_int(0, dGeo), &
+         api_coefGeo_=coefGeo, &
+         api_coefGeo_n_=size_gmsh_double(coefGeo), &
+         api_expGeo_=expGeo, &
+         api_expGeo_n_=size_gmsh_double(expGeo), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshViewSetInterpolationMatrices
+
+  !> Add a post-processing view as an `alias' of the reference view with tag
+  !! `refTag'. If `copyOptions' is set, copy the options of the reference view.
+  !! If `tag' is positive use it (and remove the view with that tag if it
+  !! already exists), otherwise associate a new tag. Return the view tag.
+  function gmshViewAddAlias(refTag, &
+                            copyOptions, &
+                            tag, &
+                            ierr)
+    interface
+    function C_API(refTag, &
+                   copyOptions, &
+                   tag, &
+                   ierr_) &
+      bind(C, name="gmshViewAddAlias")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), value, intent(in) :: refTag
+      integer(c_int), value, intent(in) :: copyOptions
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshViewAddAlias
+    integer, intent(in) :: refTag
+    logical, intent(in), optional :: copyOptions
+    integer, intent(in), optional :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshViewAddAlias = C_API(refTag=int(refTag, c_int), &
+                       copyOptions=optval_c_bool(.false., copyOptions), &
+                       tag=optval_c_int(-1, tag), &
+                       ierr_=ierr)
+    ! Post processing
+  end function gmshViewAddAlias
+
+  !> Combine elements (if `what' == "elements") or steps (if `what' == "steps")
+  !! of all views (`how' == "all"), all visible views (`how' == "visible") or
+  !! all views having the same name (`how' == "name"). Remove original views if
+  !! `remove' is set.
+  subroutine gmshViewCombine(what, &
+                             how, &
+                             remove, &
+                             copyOptions, &
+                             ierr)
+    interface
+    subroutine C_API(what, &
+                     how, &
+                     remove, &
+                     copyOptions, &
+                     ierr_) &
+      bind(C, name="gmshViewCombine")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: what
+      character(len=1, kind=c_char), dimension(*), intent(in) :: how
+      integer(c_int), value, intent(in) :: remove
+      integer(c_int), value, intent(in) :: copyOptions
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: what
+    character(len=*), intent(in) :: how
+    logical, intent(in), optional :: remove
+    logical, intent(in), optional :: copyOptions
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(what=istring_(what), &
+         how=istring_(how), &
+         remove=optval_c_bool(.true., remove), &
+         copyOptions=optval_c_bool(.true., copyOptions), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshViewCombine
+
+  !> Probe the view `tag' for its `value' at point (`x', `y', `z'). If no match
+  !! is found, `value' is returned empty. Return only the value at step `step'
+  !! is `step' is positive. Return only values with `numComp' if `numComp' is
+  !! positive. Return the gradient of the `value' if `gradient' is set. If
+  !! `distanceMax' is zero, only return a result if an exact match inside an
+  !! element in the view is found; if `distanceMax' is positive and an exact
+  !! match is not found, return the value at the closest node if it is closer
+  !! than `distanceMax'; if `distanceMax' is negative and an exact match is not
+  !! found, always return the value at the closest node. The distance to the
+  !! match is returned in `distance'. Return the result from the element
+  !! described by its coordinates if `xElementCoord', `yElementCoord' and
+  !! `zElementCoord' are provided. If `dim' is >= 0, return only matches from
+  !! elements of the specified dimension.
+  subroutine gmshViewProbe(tag, &
+                           x, &
+                           y, &
+                           z, &
+                           value, &
+                           distance, &
+                           step, &
+                           numComp, &
+                           gradient, &
+                           distanceMax, &
+                           xElemCoord, &
+                           yElemCoord, &
+                           zElemCoord, &
+                           dim, &
+                           ierr)
+    interface
+    subroutine C_API(tag, &
+                     x, &
+                     y, &
+                     z, &
+                     api_value_, &
+                     api_value_n_, &
+                     distance, &
+                     step, &
+                     numComp, &
+                     gradient, &
+                     distanceMax, &
+                     api_xElemCoord_, &
+                     api_xElemCoord_n_, &
+                     api_yElemCoord_, &
+                     api_yElemCoord_n_, &
+                     api_zElemCoord_, &
+                     api_zElemCoord_n_, &
+                     dim, &
+                     ierr_) &
+      bind(C, name="gmshViewProbe")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      real(c_double), value, intent(in) :: x
+      real(c_double), value, intent(in) :: y
+      real(c_double), value, intent(in) :: z
+      type(c_ptr), intent(out) :: api_value_
+      integer(c_size_t) :: api_value_n_
+      real(c_double) :: distance
+      integer(c_int), value, intent(in) :: step
+      integer(c_int), value, intent(in) :: numComp
+      integer(c_int), value, intent(in) :: gradient
+      real(c_double), value, intent(in) :: distanceMax
+      real(c_double), dimension(*), optional :: api_xElemCoord_
+      integer(c_size_t), value, intent(in) :: api_xElemCoord_n_
+      real(c_double), dimension(*), optional :: api_yElemCoord_
+      integer(c_size_t), value, intent(in) :: api_yElemCoord_n_
+      real(c_double), dimension(*), optional :: api_zElemCoord_
+      integer(c_size_t), value, intent(in) :: api_zElemCoord_n_
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    real(c_double), intent(in) :: x
+    real(c_double), intent(in) :: y
+    real(c_double), intent(in) :: z
+    real(c_double), dimension(:), allocatable, intent(out) :: value
+    real(c_double) :: distance
+    integer, intent(in), optional :: step
+    integer, intent(in), optional :: numComp
+    logical, intent(in), optional :: gradient
+    real(c_double), intent(in), optional :: distanceMax
+    real(c_double), dimension(:), intent(in), optional :: xElemCoord
+    real(c_double), dimension(:), intent(in), optional :: yElemCoord
+    real(c_double), dimension(:), intent(in), optional :: zElemCoord
+    integer, intent(in), optional :: dim
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_value_
+    integer(c_size_t) :: api_value_n_
+    call C_API(tag=int(tag, c_int), &
+         x=real(x, c_double), &
+         y=real(y, c_double), &
+         z=real(z, c_double), &
+         api_value_=api_value_, &
+         api_value_n_=api_value_n_, &
+         distance=distance, &
+         step=optval_c_int(-1, step), &
+         numComp=optval_c_int(-1, numComp), &
+         gradient=optval_c_bool(.false., gradient), &
+         distanceMax=optval_c_double(0., distanceMax), &
+         api_xElemCoord_=xElemCoord, &
+         api_xElemCoord_n_=size_gmsh_double(xElemCoord), &
+         api_yElemCoord_=yElemCoord, &
+         api_yElemCoord_n_=size_gmsh_double(yElemCoord), &
+         api_zElemCoord_=zElemCoord, &
+         api_zElemCoord_n_=size_gmsh_double(zElemCoord), &
+         dim=optval_c_int(-1, dim), &
+         ierr_=ierr)
+    ! Post processing
+    value = ovectordouble_(api_value_, &
+      api_value_n_)
+  end subroutine gmshViewProbe
+
+  !> Write the view to a file `fileName'. The export format is determined by the
+  !! file extension. Append to the file if `append' is set.
+  subroutine gmshViewWrite(tag, &
+                           fileName, &
+                           append, &
+                           ierr)
+    interface
+    subroutine C_API(tag, &
+                     fileName, &
+                     append, &
+                     ierr_) &
+      bind(C, name="gmshViewWrite")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      character(len=1, kind=c_char), dimension(*), intent(in) :: fileName
+      integer(c_int), value, intent(in) :: append
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    character(len=*), intent(in) :: fileName
+    logical, intent(in), optional :: append
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(tag=int(tag, c_int), &
+         fileName=istring_(fileName), &
+         append=optval_c_bool(.false., append), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshViewWrite
+
+  !> Set the global visibility of the view `tag' per window to `value', where
+  !! `windowIndex' identifies the window in the window list.
+  subroutine gmshViewSetVisibilityPerWindow(tag, &
+                                            value, &
+                                            windowIndex, &
+                                            ierr)
+    interface
+    subroutine C_API(tag, &
+                     value, &
+                     windowIndex, &
+                     ierr_) &
+      bind(C, name="gmshViewSetVisibilityPerWindow")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), value, intent(in) :: value
+      integer(c_int), value, intent(in) :: windowIndex
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    integer, intent(in) :: value
+    integer, intent(in), optional :: windowIndex
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(tag=int(tag, c_int), &
+         value=int(value, c_int), &
+         windowIndex=optval_c_int(0, windowIndex), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshViewSetVisibilityPerWindow
+
+  !> Set the numerical option `name' to value `value' for the view with tag
+  !! `tag'.
+  subroutine gmshViewOptionSetNumber(tag, &
+                                     name, &
+                                     value, &
+                                     ierr)
+    interface
+    subroutine C_API(tag, &
+                     name, &
+                     value, &
+                     ierr_) &
+      bind(C, name="gmshViewOptionSetNumber")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      real(c_double), value, intent(in) :: value
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    character(len=*), intent(in) :: name
+    real(c_double), intent(in) :: value
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(tag=int(tag, c_int), &
+         name=istring_(name), &
+         value=real(value, c_double), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshViewOptionSetNumber
+
+  !> Get the `value' of the numerical option `name' for the view with tag `tag'.
+  subroutine gmshViewOptionGetNumber(tag, &
+                                     name, &
+                                     value, &
+                                     ierr)
+    interface
+    subroutine C_API(tag, &
+                     name, &
+                     value, &
+                     ierr_) &
+      bind(C, name="gmshViewOptionGetNumber")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      real(c_double) :: value
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    character(len=*), intent(in) :: name
+    real(c_double) :: value
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(tag=int(tag, c_int), &
+         name=istring_(name), &
+         value=value, &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshViewOptionGetNumber
+
+  !> Set the string option `name' to value `value' for the view with tag `tag'.
+  subroutine gmshViewOptionSetString(tag, &
+                                     name, &
+                                     value, &
+                                     ierr)
+    interface
+    subroutine C_API(tag, &
+                     name, &
+                     value, &
+                     ierr_) &
+      bind(C, name="gmshViewOptionSetString")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      character(len=1, kind=c_char), dimension(*), intent(in) :: value
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    character(len=*), intent(in) :: name
+    character(len=*), intent(in) :: value
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(tag=int(tag, c_int), &
+         name=istring_(name), &
+         value=istring_(value), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshViewOptionSetString
+
+  !> Get the `value' of the string option `name' for the view with tag `tag'.
+  subroutine gmshViewOptionGetString(tag, &
+                                     name, &
+                                     value, &
+                                     ierr)
+    interface
+    subroutine C_API(tag, &
+                     name, &
+                     api_value_, &
+                     ierr_) &
+      bind(C, name="gmshViewOptionGetString")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      character(kind=c_char), dimension(*) :: api_value_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    character(len=*), intent(in) :: name
+    character(len=:), allocatable, intent(out) :: value
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(tag=int(tag, c_int), &
+         name=istring_(name), &
+         api_value_=value, &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshViewOptionGetString
+
+  !> Set the color option `name' to the RGBA value (`r', `g', `b', `a') for the
+  !! view with tag `tag', where where `r', `g', `b' and `a' should be integers
+  !! between 0 and 255.
+  subroutine gmshViewOptionSetColor(tag, &
+                                    name, &
+                                    r, &
+                                    g, &
+                                    b, &
+                                    a, &
+                                    ierr)
+    interface
+    subroutine C_API(tag, &
+                     name, &
+                     r, &
+                     g, &
+                     b, &
+                     a, &
+                     ierr_) &
+      bind(C, name="gmshViewOptionSetColor")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      integer(c_int), value, intent(in) :: r
+      integer(c_int), value, intent(in) :: g
+      integer(c_int), value, intent(in) :: b
+      integer(c_int), value, intent(in) :: a
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    character(len=*), intent(in) :: name
+    integer, intent(in) :: r
+    integer, intent(in) :: g
+    integer, intent(in) :: b
+    integer, intent(in), optional :: a
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(tag=int(tag, c_int), &
+         name=istring_(name), &
+         r=int(r, c_int), &
+         g=int(g, c_int), &
+         b=int(b, c_int), &
+         a=optval_c_int(255, a), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshViewOptionSetColor
+
+  !> Get the `r', `g', `b', `a' value of the color option `name' for the view
+  !! with tag `tag'.
+  subroutine gmshViewOptionGetColor(tag, &
+                                    name, &
+                                    r, &
+                                    g, &
+                                    b, &
+                                    a, &
+                                    ierr)
+    interface
+    subroutine C_API(tag, &
+                     name, &
+                     r, &
+                     g, &
+                     b, &
+                     a, &
+                     ierr_) &
+      bind(C, name="gmshViewOptionGetColor")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: tag
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      integer(c_int) :: r
+      integer(c_int) :: g
+      integer(c_int) :: b
+      integer(c_int) :: a
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: tag
+    character(len=*), intent(in) :: name
+    integer(c_int) :: r
+    integer(c_int) :: g
+    integer(c_int) :: b
+    integer(c_int) :: a
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(tag=int(tag, c_int), &
+         name=istring_(name), &
+         r=r, &
+         g=g, &
+         b=b, &
+         a=a, &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshViewOptionGetColor
+
+  !> Copy the options from the view with tag `refTag' to the view with tag
+  !! `tag'.
+  subroutine gmshViewOptionCopy(refTag, &
+                                tag, &
+                                ierr)
+    interface
+    subroutine C_API(refTag, &
+                     tag, &
+                     ierr_) &
+      bind(C, name="gmshViewOptionCopy")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: refTag
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: refTag
+    integer, intent(in) :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(refTag=int(refTag, c_int), &
+         tag=int(tag, c_int), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshViewOptionCopy
+
+  !> Set the numerical option `option' to the value `value' for plugin `name'.
+  subroutine gmshPluginSetNumber(name, &
+                                 option, &
+                                 value, &
+                                 ierr)
+    interface
+    subroutine C_API(name, &
+                     option, &
+                     value, &
+                     ierr_) &
+      bind(C, name="gmshPluginSetNumber")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      character(len=1, kind=c_char), dimension(*), intent(in) :: option
+      real(c_double), value, intent(in) :: value
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: name
+    character(len=*), intent(in) :: option
+    real(c_double), intent(in) :: value
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(name=istring_(name), &
+         option=istring_(option), &
+         value=real(value, c_double), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshPluginSetNumber
+
+  !> Set the string option `option' to the value `value' for plugin `name'.
+  subroutine gmshPluginSetString(name, &
+                                 option, &
+                                 value, &
+                                 ierr)
+    interface
+    subroutine C_API(name, &
+                     option, &
+                     value, &
+                     ierr_) &
+      bind(C, name="gmshPluginSetString")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      character(len=1, kind=c_char), dimension(*), intent(in) :: option
+      character(len=1, kind=c_char), dimension(*), intent(in) :: value
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: name
+    character(len=*), intent(in) :: option
+    character(len=*), intent(in) :: value
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(name=istring_(name), &
+         option=istring_(option), &
+         value=istring_(value), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshPluginSetString
+
+  !> Run the plugin `name'. Return the tag of the created view (if any).
+  function gmshPluginRun(name, &
+                         ierr)
+    interface
+    function C_API(name, &
+                   ierr_) &
+      bind(C, name="gmshPluginRun")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshPluginRun
+    character(len=*), intent(in) :: name
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshPluginRun = C_API(name=istring_(name), &
+                    ierr_=ierr)
+    ! Post processing
+  end function gmshPluginRun
+
+  !> Draw all the OpenGL scenes.
+  subroutine gmshGraphicsDraw(ierr)
+    interface
+    subroutine C_API(ierr_) &
+      bind(C, name="gmshGraphicsDraw")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(ierr_=ierr)
+    ! Post processing
+  end subroutine gmshGraphicsDraw
+
+  !> Create the FLTK graphical user interface. Can only be called in the main
+  !! thread.
+  subroutine gmshFltkInitialize(ierr)
+    interface
+    subroutine C_API(ierr_) &
+      bind(C, name="gmshFltkInitialize")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(ierr_=ierr)
+    ! Post processing
+  end subroutine gmshFltkInitialize
+
+  !> Close the FLTK graphical user interface. Can only be called in the main
+  !! thread.
+  subroutine gmshFltkFinalize(ierr)
+    interface
+    subroutine C_API(ierr_) &
+      bind(C, name="gmshFltkFinalize")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(ierr_=ierr)
+    ! Post processing
+  end subroutine gmshFltkFinalize
+
+  !> Wait at most `time' seconds for user interface events and return. If `time'
+  !! < 0, wait indefinitely. First automatically create the user interface if it
+  !! has not yet been initialized. Can only be called in the main thread.
+  subroutine gmshFltkWait(time, &
+                          ierr)
+    interface
+    subroutine C_API(time, &
+                     ierr_) &
+      bind(C, name="gmshFltkWait")
+      use, intrinsic :: iso_c_binding
+      real(c_double), value, intent(in) :: time
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    real(c_double), intent(in), optional :: time
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(time=optval_c_double(-1., time), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshFltkWait
+
+  !> Update the user interface (potentially creating new widgets and windows).
+  !! First automatically create the user interface if it has not yet been
+  !! initialized. Can only be called in the main thread: use `awake("update")'
+  !! to trigger an update of the user interface from another thread.
+  subroutine gmshFltkUpdate(ierr)
+    interface
+    subroutine C_API(ierr_) &
+      bind(C, name="gmshFltkUpdate")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(ierr_=ierr)
+    ! Post processing
+  end subroutine gmshFltkUpdate
+
+  !> Awake the main user interface thread and process pending events, and
+  !! optionally perform an action (currently the only `action' allowed is
+  !! "update").
+  subroutine gmshFltkAwake(action, &
+                           ierr)
+    interface
+    subroutine C_API(action, &
+                     ierr_) &
+      bind(C, name="gmshFltkAwake")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in), optional :: action
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in), optional :: action
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(action=istring_(optval_c_str("", action)), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshFltkAwake
+
+  !> Block the current thread until it can safely modify the user interface.
+  subroutine gmshFltkLock(ierr)
+    interface
+    subroutine C_API(ierr_) &
+      bind(C, name="gmshFltkLock")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(ierr_=ierr)
+    ! Post processing
+  end subroutine gmshFltkLock
+
+  !> Release the lock that was set using lock.
+  subroutine gmshFltkUnlock(ierr)
+    interface
+    subroutine C_API(ierr_) &
+      bind(C, name="gmshFltkUnlock")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(ierr_=ierr)
+    ! Post processing
+  end subroutine gmshFltkUnlock
+
+  !> Run the event loop of the graphical user interface, i.e. repeatedly call
+  !! `wait()'. First automatically create the user interface if it has not yet
+  !! been initialized. Can only be called in the main thread.
+  subroutine gmshFltkRun(ierr)
+    interface
+    subroutine C_API(ierr_) &
+      bind(C, name="gmshFltkRun")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(ierr_=ierr)
+    ! Post processing
+  end subroutine gmshFltkRun
+
+  !> Check if the user interface is available (e.g. to detect if it has been
+  !! closed).
+  function gmshFltkIsAvailable(ierr)
+    interface
+    function C_API(ierr_) &
+      bind(C, name="gmshFltkIsAvailable")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshFltkIsAvailable
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshFltkIsAvailable = C_API(ierr_=ierr)
+    ! Post processing
+  end function gmshFltkIsAvailable
+
+  !> Select entities in the user interface. If `dim' is >= 0, return only the
+  !! entities of the specified dimension (e.g. points if `dim' == 0).
+  function gmshFltkSelectEntities(dimTags, &
+                                  dim, &
+                                  ierr)
+    interface
+    function C_API(api_dimTags_, &
+                   api_dimTags_n_, &
+                   dim, &
+                   ierr_) &
+      bind(C, name="gmshFltkSelectEntities")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      type(c_ptr), intent(out) :: api_dimTags_
+      integer(c_size_t), intent(out) :: api_dimTags_n_
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshFltkSelectEntities
+    integer(c_int), dimension(:,:), allocatable, intent(out) :: dimTags
+    integer, intent(in), optional :: dim
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_dimTags_
+    integer(c_size_t) :: api_dimTags_n_
+    gmshFltkSelectEntities = C_API(api_dimTags_=api_dimTags_, &
+                             api_dimTags_n_=api_dimTags_n_, &
+                             dim=optval_c_int(-1, dim), &
+                             ierr_=ierr)
+    ! Post processing
+    dimTags = ovectorpair_(api_dimTags_, &
+      api_dimTags_n_)
+  end function gmshFltkSelectEntities
+
+  !> Select elements in the user interface.
+  function gmshFltkSelectElements(elementTags, &
+                                  ierr)
+    interface
+    function C_API(api_elementTags_, &
+                   api_elementTags_n_, &
+                   ierr_) &
+      bind(C, name="gmshFltkSelectElements")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      type(c_ptr), intent(out) :: api_elementTags_
+      integer(c_size_t), intent(out) :: api_elementTags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshFltkSelectElements
+    integer(c_size_t), dimension(:), allocatable, intent(out) :: elementTags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_elementTags_
+    integer(c_size_t) :: api_elementTags_n_
+    gmshFltkSelectElements = C_API(api_elementTags_=api_elementTags_, &
+                             api_elementTags_n_=api_elementTags_n_, &
+                             ierr_=ierr)
+    ! Post processing
+    elementTags = ovectorsize_(api_elementTags_, &
+      api_elementTags_n_)
+  end function gmshFltkSelectElements
+
+  !> Select views in the user interface.
+  function gmshFltkSelectViews(viewTags, &
+                               ierr)
+    interface
+    function C_API(api_viewTags_, &
+                   api_viewTags_n_, &
+                   ierr_) &
+      bind(C, name="gmshFltkSelectViews")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      type(c_ptr), intent(out) :: api_viewTags_
+      integer(c_size_t), intent(out) :: api_viewTags_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshFltkSelectViews
+    integer(c_int), dimension(:), allocatable, intent(out) :: viewTags
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_viewTags_
+    integer(c_size_t) :: api_viewTags_n_
+    gmshFltkSelectViews = C_API(api_viewTags_=api_viewTags_, &
+                          api_viewTags_n_=api_viewTags_n_, &
+                          ierr_=ierr)
+    ! Post processing
+    viewTags = ovectorint_(api_viewTags_, &
+      api_viewTags_n_)
+  end function gmshFltkSelectViews
+
+  !> Split the current window horizontally (if `how' = "h") or vertically (if
+  !! `how' = "v"), using ratio `ratio'. If `how' = "u", restore a single window.
+  subroutine gmshFltkSplitCurrentWindow(how, &
+                                        ratio, &
+                                        ierr)
+    interface
+    subroutine C_API(how, &
+                     ratio, &
+                     ierr_) &
+      bind(C, name="gmshFltkSplitCurrentWindow")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in), optional :: how
+      real(c_double), value, intent(in) :: ratio
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in), optional :: how
+    real(c_double), intent(in), optional :: ratio
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(how=istring_(optval_c_str("v", how)), &
+         ratio=optval_c_double(0.5, ratio), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshFltkSplitCurrentWindow
+
+  !> Set the current window by speficying its index (starting at 0) in the list
+  !! of all windows. When new windows are created by splits, new windows are
+  !! appended at the end of the list.
+  subroutine gmshFltkSetCurrentWindow(windowIndex, &
+                                      ierr)
+    interface
+    subroutine C_API(windowIndex, &
+                     ierr_) &
+      bind(C, name="gmshFltkSetCurrentWindow")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: windowIndex
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in), optional :: windowIndex
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(windowIndex=optval_c_int(0, windowIndex), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshFltkSetCurrentWindow
+
+  !> Set a status message in the current window. If `graphics' is set, display
+  !! the message inside the graphic window instead of the status bar.
+  subroutine gmshFltkSetStatusMessage(message, &
+                                      graphics, &
+                                      ierr)
+    interface
+    subroutine C_API(message, &
+                     graphics, &
+                     ierr_) &
+      bind(C, name="gmshFltkSetStatusMessage")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: message
+      integer(c_int), value, intent(in) :: graphics
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: message
+    logical, intent(in), optional :: graphics
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(message=istring_(message), &
+         graphics=optval_c_bool(.false., graphics), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshFltkSetStatusMessage
+
+  !> Show context window for the entity of dimension `dim' and tag `tag'.
+  subroutine gmshFltkShowContextWindow(dim, &
+                                       tag, &
+                                       ierr)
+    interface
+    subroutine C_API(dim, &
+                     tag, &
+                     ierr_) &
+      bind(C, name="gmshFltkShowContextWindow")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), value, intent(in) :: dim
+      integer(c_int), value, intent(in) :: tag
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer, intent(in) :: dim
+    integer, intent(in) :: tag
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(dim=int(dim, c_int), &
+         tag=int(tag, c_int), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshFltkShowContextWindow
+
+  !> Open the `name' item in the menu tree.
+  subroutine gmshFltkOpenTreeItem(name, &
+                                  ierr)
+    interface
+    subroutine C_API(name, &
+                     ierr_) &
+      bind(C, name="gmshFltkOpenTreeItem")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: name
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(name=istring_(name), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshFltkOpenTreeItem
+
+  !> Close the `name' item in the menu tree.
+  subroutine gmshFltkCloseTreeItem(name, &
+                                   ierr)
+    interface
+    subroutine C_API(name, &
+                     ierr_) &
+      bind(C, name="gmshFltkCloseTreeItem")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: name
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(name=istring_(name), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshFltkCloseTreeItem
+
+  !> Get the names of the variables in the Gmsh parser matching the `search'
+  !! regular expression. If `search' is empty, return all the names.
+  subroutine gmshParserGetNames(names, &
+                                search, &
+                                ierr)
+    interface
+    subroutine C_API(api_names_, &
+                     api_names_n_, &
+                     search, &
+                     ierr_) &
+      bind(C, name="gmshParserGetNames")
+      use, intrinsic :: iso_c_binding
+      type(c_ptr), intent(out) :: api_names_
+      integer(c_size_t), intent(out) :: api_names_n_
+      character(len=1, kind=c_char), dimension(*), intent(in), optional :: search
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=GMSH_API_MAX_STR_LEN), dimension(:), allocatable, intent(out) :: names
+    character(len=*), intent(in), optional :: search
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_names_
+    integer(c_size_t) :: api_names_n_
+    call C_API(api_names_=api_names_, &
+         api_names_n_=api_names_n_, &
+         search=istring_(optval_c_str("", search)), &
+         ierr_=ierr)
+    ! Post processing
+    names = ovectorstring_(api_names_, &
+      api_names_n_)
+  end subroutine gmshParserGetNames
+
+  !> Set the value of the number variable `name' in the Gmsh parser. Create the
+  !! variable if it does not exist; update the value if the variable exists.
+  subroutine gmshParserSetNumber(name, &
+                                 value, &
+                                 ierr)
+    interface
+    subroutine C_API(name, &
+                     api_value_, &
+                     api_value_n_, &
+                     ierr_) &
+      bind(C, name="gmshParserSetNumber")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      real(c_double), dimension(*) :: api_value_
+      integer(c_size_t), value, intent(in) :: api_value_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: name
+    real(c_double), dimension(:), intent(in) :: value
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(name=istring_(name), &
+         api_value_=value, &
+         api_value_n_=size_gmsh_double(value), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshParserSetNumber
+
+  !> Set the value of the string variable `name' in the Gmsh parser. Create the
+  !! variable if it does not exist; update the value if the variable exists.
+  subroutine gmshParserSetString(name, &
+                                 value, &
+                                 ierr)
+    interface
+    subroutine C_API(name, &
+                     api_value_, &
+                     api_value_n_, &
+                     ierr_) &
+      bind(C, name="gmshParserSetString")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      type(c_ptr), dimension(*) :: api_value_
+      integer(c_size_t), value, intent(in) :: api_value_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: name
+    character(len=*), dimension(:), intent(in) :: value
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    character(len=GMSH_API_MAX_STR_LEN, kind=c_char), allocatable :: api_value_strs(:)
+    type(c_ptr), allocatable :: api_value_(:)
+    call ivectorstring_(value, &
+      api_value_strs, &
+      api_value_)
+    call C_API(name=istring_(name), &
+         api_value_=api_value_, &
+         api_value_n_=size_gmsh_str(value), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshParserSetString
+
+  !> Get the value of the number variable `name' from the Gmsh parser. Return an
+  !! empty vector if the variable does not exist.
+  subroutine gmshParserGetNumber(name, &
+                                 value, &
+                                 ierr)
+    interface
+    subroutine C_API(name, &
+                     api_value_, &
+                     api_value_n_, &
+                     ierr_) &
+      bind(C, name="gmshParserGetNumber")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      type(c_ptr), intent(out) :: api_value_
+      integer(c_size_t) :: api_value_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: name
+    real(c_double), dimension(:), allocatable, intent(out) :: value
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_value_
+    integer(c_size_t) :: api_value_n_
+    call C_API(name=istring_(name), &
+         api_value_=api_value_, &
+         api_value_n_=api_value_n_, &
+         ierr_=ierr)
+    ! Post processing
+    value = ovectordouble_(api_value_, &
+      api_value_n_)
+  end subroutine gmshParserGetNumber
+
+  !> Get the value of the string variable `name' from the Gmsh parser. Return an
+  !! empty vector if the variable does not exist.
+  subroutine gmshParserGetString(name, &
+                                 value, &
+                                 ierr)
+    interface
+    subroutine C_API(name, &
+                     api_value_, &
+                     api_value_n_, &
+                     ierr_) &
+      bind(C, name="gmshParserGetString")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      type(c_ptr), intent(out) :: api_value_
+      integer(c_size_t), intent(out) :: api_value_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: name
+    character(len=GMSH_API_MAX_STR_LEN), dimension(:), allocatable, intent(out) :: value
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_value_
+    integer(c_size_t) :: api_value_n_
+    call C_API(name=istring_(name), &
+         api_value_=api_value_, &
+         api_value_n_=api_value_n_, &
+         ierr_=ierr)
+    ! Post processing
+    value = ovectorstring_(api_value_, &
+      api_value_n_)
+  end subroutine gmshParserGetString
+
+  !> Clear all the Gmsh parser variables, or remove a single variable if `name'
+  !! is given.
+  subroutine gmshParserClear(name, &
+                             ierr)
+    interface
+    subroutine C_API(name, &
+                     ierr_) &
+      bind(C, name="gmshParserClear")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in), optional :: name
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in), optional :: name
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(name=istring_(optval_c_str("", name)), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshParserClear
+
+  !> Parse the file `fileName' with the Gmsh parser.
+  subroutine gmshParserParse(fileName, &
+                             ierr)
+    interface
+    subroutine C_API(fileName, &
+                     ierr_) &
+      bind(C, name="gmshParserParse")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: fileName
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: fileName
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(fileName=istring_(fileName), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshParserParse
+
+  !> Set one or more parameters in the ONELAB database, encoded in `format'.
+  subroutine gmshOnelabSet(data, &
+                           format, &
+                           ierr)
+    interface
+    subroutine C_API(data, &
+                     format, &
+                     ierr_) &
+      bind(C, name="gmshOnelabSet")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: data
+      character(len=1, kind=c_char), dimension(*), intent(in), optional :: format
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: data
+    character(len=*), intent(in), optional :: format
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(data=istring_(data), &
+         format=istring_(optval_c_str("json", format)), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshOnelabSet
+
+  !> Get all the parameters (or a single one if `name' is specified) from the
+  !! ONELAB database, encoded in `format'.
+  subroutine gmshOnelabGet(data, &
+                           name, &
+                           format, &
+                           ierr)
+    interface
+    subroutine C_API(api_data_, &
+                     name, &
+                     format, &
+                     ierr_) &
+      bind(C, name="gmshOnelabGet")
+      use, intrinsic :: iso_c_binding
+      character(kind=c_char), dimension(*) :: api_data_
+      character(len=1, kind=c_char), dimension(*), intent(in), optional :: name
+      character(len=1, kind=c_char), dimension(*), intent(in), optional :: format
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=:), allocatable, intent(out) :: data
+    character(len=*), intent(in), optional :: name
+    character(len=*), intent(in), optional :: format
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_data_=data, &
+         name=istring_(optval_c_str("", name)), &
+         format=istring_(optval_c_str("json", format)), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshOnelabGet
+
+  !> Get the names of the parameters in the ONELAB database matching the
+  !! `search' regular expression. If `search' is empty, return all the names.
+  subroutine gmshOnelabGetNames(names, &
+                                search, &
+                                ierr)
+    interface
+    subroutine C_API(api_names_, &
+                     api_names_n_, &
+                     search, &
+                     ierr_) &
+      bind(C, name="gmshOnelabGetNames")
+      use, intrinsic :: iso_c_binding
+      type(c_ptr), intent(out) :: api_names_
+      integer(c_size_t), intent(out) :: api_names_n_
+      character(len=1, kind=c_char), dimension(*), intent(in), optional :: search
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=GMSH_API_MAX_STR_LEN), dimension(:), allocatable, intent(out) :: names
+    character(len=*), intent(in), optional :: search
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_names_
+    integer(c_size_t) :: api_names_n_
+    call C_API(api_names_=api_names_, &
+         api_names_n_=api_names_n_, &
+         search=istring_(optval_c_str("", search)), &
+         ierr_=ierr)
+    ! Post processing
+    names = ovectorstring_(api_names_, &
+      api_names_n_)
+  end subroutine gmshOnelabGetNames
+
+  !> Set the value of the number parameter `name' in the ONELAB database. Create
+  !! the parameter if it does not exist; update the value if the parameter
+  !! exists.
+  subroutine gmshOnelabSetNumber(name, &
+                                 value, &
+                                 ierr)
+    interface
+    subroutine C_API(name, &
+                     api_value_, &
+                     api_value_n_, &
+                     ierr_) &
+      bind(C, name="gmshOnelabSetNumber")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      real(c_double), dimension(*) :: api_value_
+      integer(c_size_t), value, intent(in) :: api_value_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: name
+    real(c_double), dimension(:), intent(in) :: value
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(name=istring_(name), &
+         api_value_=value, &
+         api_value_n_=size_gmsh_double(value), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshOnelabSetNumber
+
+  !> Set the value of the string parameter `name' in the ONELAB database. Create
+  !! the parameter if it does not exist; update the value if the parameter
+  !! exists.
+  subroutine gmshOnelabSetString(name, &
+                                 value, &
+                                 ierr)
+    interface
+    subroutine C_API(name, &
+                     api_value_, &
+                     api_value_n_, &
+                     ierr_) &
+      bind(C, name="gmshOnelabSetString")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      type(c_ptr), dimension(*) :: api_value_
+      integer(c_size_t), value, intent(in) :: api_value_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: name
+    character(len=*), dimension(:), intent(in) :: value
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    character(len=GMSH_API_MAX_STR_LEN, kind=c_char), allocatable :: api_value_strs(:)
+    type(c_ptr), allocatable :: api_value_(:)
+    call ivectorstring_(value, &
+      api_value_strs, &
+      api_value_)
+    call C_API(name=istring_(name), &
+         api_value_=api_value_, &
+         api_value_n_=size_gmsh_str(value), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshOnelabSetString
+
+  !> Get the value of the number parameter `name' from the ONELAB database.
+  !! Return an empty vector if the parameter does not exist.
+  subroutine gmshOnelabGetNumber(name, &
+                                 value, &
+                                 ierr)
+    interface
+    subroutine C_API(name, &
+                     api_value_, &
+                     api_value_n_, &
+                     ierr_) &
+      bind(C, name="gmshOnelabGetNumber")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      type(c_ptr), intent(out) :: api_value_
+      integer(c_size_t) :: api_value_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: name
+    real(c_double), dimension(:), allocatable, intent(out) :: value
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_value_
+    integer(c_size_t) :: api_value_n_
+    call C_API(name=istring_(name), &
+         api_value_=api_value_, &
+         api_value_n_=api_value_n_, &
+         ierr_=ierr)
+    ! Post processing
+    value = ovectordouble_(api_value_, &
+      api_value_n_)
+  end subroutine gmshOnelabGetNumber
+
+  !> Get the value of the string parameter `name' from the ONELAB database.
+  !! Return an empty vector if the parameter does not exist.
+  subroutine gmshOnelabGetString(name, &
+                                 value, &
+                                 ierr)
+    interface
+    subroutine C_API(name, &
+                     api_value_, &
+                     api_value_n_, &
+                     ierr_) &
+      bind(C, name="gmshOnelabGetString")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      type(c_ptr), intent(out) :: api_value_
+      integer(c_size_t), intent(out) :: api_value_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: name
+    character(len=GMSH_API_MAX_STR_LEN), dimension(:), allocatable, intent(out) :: value
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_value_
+    integer(c_size_t) :: api_value_n_
+    call C_API(name=istring_(name), &
+         api_value_=api_value_, &
+         api_value_n_=api_value_n_, &
+         ierr_=ierr)
+    ! Post processing
+    value = ovectorstring_(api_value_, &
+      api_value_n_)
+  end subroutine gmshOnelabGetString
+
+  !> Check if any parameters in the ONELAB database used by the client `name'
+  !! have been changed.
+  function gmshOnelabGetChanged(name, &
+                                ierr)
+    interface
+    function C_API(name, &
+                   ierr_) &
+      bind(C, name="gmshOnelabGetChanged")
+      use, intrinsic :: iso_c_binding
+      integer(c_int) :: C_API
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    integer(c_int) :: gmshOnelabGetChanged
+    character(len=*), intent(in) :: name
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshOnelabGetChanged = C_API(name=istring_(name), &
+                           ierr_=ierr)
+    ! Post processing
+  end function gmshOnelabGetChanged
+
+  !> Set the changed flag to value `value' for all the parameters in the ONELAB
+  !! database used by the client `name'.
+  subroutine gmshOnelabSetChanged(name, &
+                                  value, &
+                                  ierr)
+    interface
+    subroutine C_API(name, &
+                     value, &
+                     ierr_) &
+      bind(C, name="gmshOnelabSetChanged")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: name
+      integer(c_int), value, intent(in) :: value
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: name
+    integer, intent(in) :: value
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(name=istring_(name), &
+         value=int(value, c_int), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshOnelabSetChanged
+
+  !> Clear the ONELAB database, or remove a single parameter if `name' is given.
+  subroutine gmshOnelabClear(name, &
+                             ierr)
+    interface
+    subroutine C_API(name, &
+                     ierr_) &
+      bind(C, name="gmshOnelabClear")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in), optional :: name
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in), optional :: name
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(name=istring_(optval_c_str("", name)), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshOnelabClear
+
+  !> Run a ONELAB client. If `name' is provided, create a new ONELAB client with
+  !! name `name' and executes `command'. If not, try to run a client that might
+  !! be linked to the processed input files.
+  subroutine gmshOnelabRun(name, &
+                           command, &
+                           ierr)
+    interface
+    subroutine C_API(name, &
+                     command, &
+                     ierr_) &
+      bind(C, name="gmshOnelabRun")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in), optional :: name
+      character(len=1, kind=c_char), dimension(*), intent(in), optional :: command
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in), optional :: name
+    character(len=*), intent(in), optional :: command
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(name=istring_(optval_c_str("", name)), &
+         command=istring_(optval_c_str("", command)), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshOnelabRun
+
+  !> Write a `message'. `level' can be "info", "warning" or "error".
+  subroutine gmshLoggerWrite(message, &
+                             level, &
+                             ierr)
+    interface
+    subroutine C_API(message, &
+                     level, &
+                     ierr_) &
+      bind(C, name="gmshLoggerWrite")
+      use, intrinsic :: iso_c_binding
+      character(len=1, kind=c_char), dimension(*), intent(in) :: message
+      character(len=1, kind=c_char), dimension(*), intent(in), optional :: level
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=*), intent(in) :: message
+    character(len=*), intent(in), optional :: level
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(message=istring_(message), &
+         level=istring_(optval_c_str("info", level)), &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshLoggerWrite
+
+  !> Start logging messages.
+  subroutine gmshLoggerStart(ierr)
+    interface
+    subroutine C_API(ierr_) &
+      bind(C, name="gmshLoggerStart")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(ierr_=ierr)
+    ! Post processing
+  end subroutine gmshLoggerStart
+
+  !> Get logged messages.
+  subroutine gmshLoggerGet(log, &
+                           ierr)
+    interface
+    subroutine C_API(api_log_, &
+                     api_log_n_, &
+                     ierr_) &
+      bind(C, name="gmshLoggerGet")
+      use, intrinsic :: iso_c_binding
+      type(c_ptr), intent(out) :: api_log_
+      integer(c_size_t), intent(out) :: api_log_n_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=GMSH_API_MAX_STR_LEN), dimension(:), allocatable, intent(out) :: log
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    type(c_ptr) :: api_log_
+    integer(c_size_t) :: api_log_n_
+    call C_API(api_log_=api_log_, &
+         api_log_n_=api_log_n_, &
+         ierr_=ierr)
+    ! Post processing
+    log = ovectorstring_(api_log_, &
+      api_log_n_)
+  end subroutine gmshLoggerGet
+
+  !> Stop logging messages.
+  subroutine gmshLoggerStop(ierr)
+    interface
+    subroutine C_API(ierr_) &
+      bind(C, name="gmshLoggerStop")
+      use, intrinsic :: iso_c_binding
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(ierr_=ierr)
+    ! Post processing
+  end subroutine gmshLoggerStop
+
+  !> Return wall clock time.
+  function gmshLoggerGetWallTime(ierr)
+    interface
+    function C_API(ierr_) &
+      bind(C, name="gmshLoggerGetWallTime")
+      use, intrinsic :: iso_c_binding
+      real(c_double) :: C_API
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    real(c_double) :: gmshLoggerGetWallTime
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshLoggerGetWallTime = C_API(ierr_=ierr)
+    ! Post processing
+  end function gmshLoggerGetWallTime
+
+  !> Return CPU time.
+  function gmshLoggerGetCpuTime(ierr)
+    interface
+    function C_API(ierr_) &
+      bind(C, name="gmshLoggerGetCpuTime")
+      use, intrinsic :: iso_c_binding
+      real(c_double) :: C_API
+      integer(c_int), intent(out), optional :: ierr_
+    end function C_API
+    end interface
+    real(c_double) :: gmshLoggerGetCpuTime
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    gmshLoggerGetCpuTime = C_API(ierr_=ierr)
+    ! Post processing
+  end function gmshLoggerGetCpuTime
+
+  !> Return last error message, if any.
+  subroutine gmshLoggerGetLastError(error, &
+                                    ierr)
+    interface
+    subroutine C_API(api_error_, &
+                     ierr_) &
+      bind(C, name="gmshLoggerGetLastError")
+      use, intrinsic :: iso_c_binding
+      character(kind=c_char), dimension(*) :: api_error_
+      integer(c_int), intent(out), optional :: ierr_
+    end subroutine C_API
+    end interface
+    character(len=:), allocatable, intent(out) :: error
+    integer(c_int), intent(out), optional :: ierr
+    ! Local variables
+    call C_API(api_error_=error, &
+         ierr_=ierr)
+    ! Post processing
+  end subroutine gmshLoggerGetLastError
+
+  ! ----------------------------------------------------------------------------
+  ! GMSH size function
+  ! ----------------------------------------------------------------------------
+
+  pure integer(c_int) function optval_c_int_1(def, val) result(res)
+    integer(c_int), intent(in) :: def
+    integer(c_int), optional, intent(in) :: val
+    res = int(def, kind=c_int)
+    if (present(val)) res = int(val, kind=c_int)
+  end function optval_c_int_1
+
+  pure integer(c_size_t) function optval_c_size_t_1(def, val) result(res)
+    integer, intent(in) :: def
+    integer, optional, intent(in) :: val
+    res = int(def, kind=c_size_t)
+    if (present(val)) res = int(val, kind=c_size_t)
+  end function optval_c_size_t_1
+
+  pure integer(c_size_t) function optval_c_size_t_2(def, val) result(res)
+    integer(c_size_t), intent(in) :: def
+    integer(c_size_t), optional, intent(in) :: val
+    res = int(def, kind=c_size_t)
+    if (present(val)) res = int(val, kind=c_size_t)
+  end function optval_c_size_t_2
+
+  pure real(c_double) function optval_c_double_1(def, val) result(res)
+    real(c_double), intent(in) :: def
+    real(c_double), optional, intent(in) :: val
+    res = real(def, kind=c_double)
+    if (present(val)) res = real(val, kind=c_double)
+  end function optval_c_double_1
+
+  pure real(c_double) function optval_c_double_2(def, val) result(res)
+    real, intent(in) :: def
+    real(c_double), optional, intent(in) :: val
+    res = real(def, kind=c_double)
+    if (present(val)) res = real(val, kind=c_double)
+  end function optval_c_double_2
+
+  pure integer(c_int) function optval_c_bool(def, val) result(res)
+    logical, intent(in) :: def
+    logical, optional, intent(in) :: val
+    res = merge(1_c_int, 0_c_int, def)
+    if (present(val)) res = merge(1_c_int, 0_c_int, val)
+  end function optval_c_bool
+
+  pure function optval_c_str(def, val) result(res)
+    character(len=*), intent(in) :: def
+    character(len=*), optional, intent(in) :: val
+    character(len=:), allocatable :: res
+    if (present(val)) then
+      res = val
+    else
+      res = def
+    end if
+  end function optval_c_str
+
+  pure function optval_str_array(def, val) result(res)
+    character(len=*), intent(in) :: def(:)
+    character(len=*), optional, intent(in) :: val(:)
+    character(len=:), allocatable :: res(:)
+    if (present(val)) then
+      res = val
+    else
+      res = def
+    end if
+  end function optval_str_array
+
+  ! ----------------------------------------------------------------------------
+  ! GMSH size functions, with handling of optional arguments
+  ! ----------------------------------------------------------------------------
+
+  pure integer(c_size_t) function size_gmsh_int(v) result(n)
+    integer(c_int), optional, intent(in) :: v(:)
+    n = 0
+    if (present(v)) n = size(v, kind=c_size_t)
+  end function size_gmsh_int
+
+  pure integer(c_size_t) function size_gmsh_size(v) result(n)
+    integer(c_size_t), optional, intent(in) :: v(:)
+    n = 0
+    if (present(v)) n = size(v, kind=c_size_t)
+  end function size_gmsh_size
+
+  pure integer(c_size_t) function size_gmsh_double(v) result(n)
+    real(c_double), optional, intent(in) :: v(:)
+    n = 0
+    if (present(v)) n = size(v, kind=c_size_t)
+  end function size_gmsh_double
+
+  pure integer(c_size_t) function size_gmsh_str(v) result(n)
+    character(len=*), optional, intent(in) :: v(:)
+    n = 0
+    if (present(v)) n = size(v, kind=c_size_t)
+  end function size_gmsh_str
+
+  pure integer(c_size_t) function size_gmsh_pair(v) result(n)
+    integer(c_int), optional, intent(in) :: v(:,:)
+    n = 0
+    if (present(v)) n = size(v, kind=c_size_t)
+  end function size_gmsh_pair
+
+  pure integer(c_int) function size_gmsh_str_array(v) result(n)
+    character(len=*), optional, intent(in) :: v(:)
+    n = 1   ! can't have 0-length commands
+    if (present(v)) n = size(v, kind=c_int)
+  end function size_gmsh_str_array
+
+  ! ----------------------------------------------------------------------------
+  ! GMSH C memory management tools
+  ! ----------------------------------------------------------------------------
+
+  !> Callback to C to free any reserved memory
+  subroutine gmshFree(p)
+    interface
+      subroutine C_API(ptr) bind(C, name="gmshFree")
+        use, intrinsic :: iso_c_binding
+        type(c_ptr), value :: ptr
+      end subroutine C_API
+    end interface
+    type(c_ptr) :: p
+    call C_API(p)
+  end subroutine gmshFree
+
+  ! ----------------------------------------------------------------------------
+  ! Input routines from Fortran to C
+  ! ----------------------------------------------------------------------------
+
+  function istring_(o) result(v)
+    character(len=*), intent(in) :: o
+    character(len=:, kind=c_char), allocatable :: v
+    v = trim(o)//c_null_char
+  end function istring_
+
+  function ivectorint_(o) result(v)
+    integer(c_int), intent(in) :: o(:)
+    integer(c_int), dimension(size(o)) :: v
+    v = o
+  end function ivectorint_
+
+  function ivectorsize_(o) result(v)
+    integer(c_size_t), intent(in) :: o(:)
+    integer(c_size_t), dimension(size(o)) :: v
+    v = o
+  end function ivectorsize_
+
+  function ivectordouble_(o) result(v)
+    real(c_double), intent(in) :: o(:)
+    real(c_double), dimension(size(o)) :: v
+    v = o
+  end function ivectordouble_
+
+  subroutine ivectorstring_(o, cstrs, cptrs)
+    character(len=*), intent(in) :: o(:)
+    character(len=GMSH_API_MAX_STR_LEN, kind=c_char), target, allocatable, intent(out) :: cstrs(:)
+    type(c_ptr), allocatable, intent(out) :: cptrs(:)
+    integer :: i
+    allocate(cstrs(size(o)))    ! Return to keep references from cptrs
+    allocate(cptrs(size(o)))
+    do i = 1, size(o)
+        cstrs(i) = istring_(o(i))
+        cptrs(i) = c_loc(cstrs(i))
+    end do
+  end subroutine ivectorstring_
+
+  function ivectorpair_(o) result(v)
+    integer(c_int), intent(in) :: o(:,:)
+    integer(c_int), dimension(size(o,1),2) :: v
+    v = o
+  end function ivectorpair_
+
+  subroutine ivectorvectorint_(v, dims, cptr1, cptr2, n)
+    integer(c_int), target, intent(in) :: v(:)
+    integer(c_size_t), target, intent(in) :: dims(:)
+    type(c_ptr), intent(out) :: cptr1, cptr2
+    integer(c_size_t), intent(out) :: n
+
+    n = size(dims, kind=c_size_t)
+    cptr1 = c_loc(v)
+    cptr2 = c_loc(dims)
+  end subroutine ivectorvectorint_
+
+  subroutine ivectorvectorsize_(v, dims, cptr1, cptr2, n)
+    integer(c_size_t), target, intent(in) :: v(:)
+    integer(c_size_t), target, intent(in) :: dims(:)
+    type(c_ptr), intent(out) :: cptr1, cptr2
+    integer(c_size_t), intent(out) :: n
+
+    n = size(dims, kind=c_size_t)
+    cptr1 = c_loc(v)
+    cptr2 = c_loc(dims)
+  end subroutine ivectorvectorsize_
+
+  subroutine ivectorvectordouble_(v, dims, cptr1, cptr2, n)
+    real(c_double), target, intent(in) :: v(:)
+    integer(c_size_t), target, intent(in) :: dims(:)
+    type(c_ptr), intent(out) :: cptr1, cptr2
+    integer(c_size_t), intent(out) :: n
+
+    n = size(dims, kind=c_size_t)
+    cptr1 = c_loc(v)
+    cptr2 = c_loc(dims)
+  end subroutine ivectorvectordouble_
+
+  ! subroutine ivectorvectorpair_(v, dims, cptr1, cptr2, n)
+  !   integer(c_int), target, intent(in) :: v(:,:)
+  !   integer(c_size_t), target, intent(in) :: dims(:)
+  !   type(c_ptr), intent(out) :: cptr1, cptr2
+  !   integer(c_size_t), intent(out) :: n
+  !
+  !   n = size(dims, kind=c_size_t)
+  !   cptr1 = c_loc(v)
+  !   cptr2 = c_loc(dims)
+  ! end subroutine ivectorvectorpair_
+
+
+  ! ----------------------------------------------------------------------------
+  ! Output routines from C to Fortran
+  ! ----------------------------------------------------------------------------
+
+  function ovectorint_(cptr, n) result(v)
+    type(c_ptr), intent(inout) :: cptr
+    integer(c_size_t), intent(in) :: n
+    integer(c_int), allocatable :: v(:)
+    integer(c_int), pointer :: v_(:)
+    call c_f_pointer(cptr, v_, [n])
+    allocate(v, source=v_)
+    call gmshFree(cptr)
+  end function ovectorint_
+
+  function ovectorsize_(cptr, n) result(v)
+    type(c_ptr), intent(inout) :: cptr
+    integer(c_size_t), intent(in) :: n
+    integer(c_size_t), allocatable :: v(:)
+    integer(c_size_t), pointer :: v_(:)
+    call c_f_pointer(cptr, v_, [n])
+    allocate(v, source=v_)
+    call gmshFree(cptr)
+  end function ovectorsize_
+
+  function ovectordouble_(cptr, n) result(v)
+    type(c_ptr), intent(inout) :: cptr
+    integer(c_size_t), intent(in) :: n
+    real(c_double), allocatable :: v(:)
+    real(c_double), pointer :: v_(:)
+    call c_f_pointer(cptr, v_, [n])
+    allocate(v, source=v_)
+    call gmshFree(cptr)
+  end function ovectordouble_
+
+  function ovectorstring_(cptr, n) result(v)
+    type(c_ptr), intent(inout) :: cptr
+    integer(c_size_t), intent(in) :: n
+    character(len=GMSH_API_MAX_STR_LEN), allocatable :: v(:)
+
+    integer(c_size_t) :: i, lenstr
+    type(c_array_t), pointer :: c_array(:)
+    character(kind=c_char, len=1), pointer :: fptr(:)
+
+    call c_f_pointer(cptr, c_array, [n])
+    allocate(v(n))
+    do i = 1_c_size_t, n
+        call c_f_pointer(c_array(i)%s, fptr, &
+                         [int(GMSH_API_MAX_STR_LEN, kind=c_size_t)])
+        lenstr = cstrlen(fptr)
+        v(i) = transfer(fptr(1:lenstr), v(i))
+    end do
+    call gmshFree(cptr)
+  end function ovectorstring_
+
+  function ovectorpair_(cptr, n) result(v)
+    type(c_ptr), intent(inout) :: cptr
+    integer(c_size_t), intent(in) :: n
+    integer(c_int), allocatable :: v(:,:)
+    integer(c_int), pointer :: v_(:,:)
+    call c_f_pointer(cptr, v_, [2_c_size_t, n / 2_c_size_t])
+    allocate(v, source=v_)
+    call gmshFree(cptr)
+  end function ovectorpair_
+
+  subroutine ovectorvectorint_(cptr1, cptr2, n, v, dims)
+    type(c_ptr), intent(inout) :: cptr1, cptr2
+    integer(c_size_t), intent(in) :: n
+    integer(c_int), allocatable, intent(out) :: v(:)
+    integer(c_size_t), allocatable, intent(out) :: dims(:)
+    integer(c_int), pointer :: v_(:)
+    integer(c_size_t), pointer :: dims_(:)
+    type(c_ptr), pointer :: ptrs(:)
+    integer(c_size_t) :: i, istart, iend
+    call c_f_pointer(cptr2, dims_, [n])
+    allocate(dims, source=dims_)
+    allocate(v(sum(dims_)))
+    istart = 1
+    call c_f_pointer(cptr1, ptrs, [n])
+    do i = 1_c_size_t, n
+        iend = int(dims(i))
+        call c_f_pointer(ptrs(i), v_, [iend])
+        v(istart:iend) = v_
+        istart = istart + iend
+    end do
+    do i = 1_c_size_t, n
+        call gmshFree(ptrs(i))
+    end do
+    call gmshFree(cptr1)
+    call gmshFree(cptr2)
+  end subroutine ovectorvectorint_
+
+  subroutine ovectorvectorsize_(cptr1, cptr2, n, v, dims)
+    type(c_ptr), intent(inout) :: cptr1, cptr2
+    integer(c_size_t), intent(in) :: n
+    integer(c_size_t), allocatable, intent(out) :: v(:)
+    integer(c_size_t), allocatable, intent(out) :: dims(:)
+    integer(c_size_t), pointer :: v_(:)
+    integer(c_size_t), pointer :: dims_(:)
+    type(c_ptr), pointer :: ptrs(:)
+    integer(c_size_t) :: i, istart, iend
+    call c_f_pointer(cptr2, dims_, [n])
+    allocate(dims, source=dims_)
+    allocate(v(sum(dims_)))
+    istart = 1
+    call c_f_pointer(cptr1, ptrs, [n])
+    do i = 1_c_size_t, n
+        iend = int(dims(i))
+        call c_f_pointer(ptrs(i), v_, [iend])
+        v(istart:iend) = v_
+        istart = istart + iend
+    end do
+    do i = 1_c_size_t, n
+        call gmshFree(ptrs(i))
+    end do
+    call gmshFree(cptr1)
+    call gmshFree(cptr2)
+  end subroutine ovectorvectorsize_
+
+  subroutine ovectorvectordouble_(cptr1, cptr2, n, v, dims)
+    type(c_ptr), intent(inout) :: cptr1, cptr2
+    integer(c_size_t), intent(in) :: n
+    real(c_double), allocatable, intent(out) :: v(:)
+    integer(c_size_t), allocatable, intent(out) :: dims(:)
+    real(c_double), pointer :: v_(:)
+    integer(c_size_t), pointer :: dims_(:)
+    type(c_ptr), pointer :: ptrs(:)
+    integer(c_size_t) :: i, istart, iend
+    call c_f_pointer(cptr2, dims_, [n])
+    allocate(dims, source=dims_)
+    allocate(v(sum(dims_)))
+    istart = 1
+    call c_f_pointer(cptr1, ptrs, [n])
+    do i = 1_c_size_t, n
+        iend = int(dims(i))
+        call c_f_pointer(ptrs(i), v_, [iend])
+        v(istart:iend) = v_
+        istart = istart + iend
+    end do
+    do i = 1_c_size_t, n
+        call gmshFree(ptrs(i))
+    end do
+    call gmshFree(cptr1)
+    call gmshFree(cptr2)
+  end subroutine ovectorvectordouble_
+
+  subroutine ovectorvectorpair_(cptr1, cptr2, n, v, dims)
+    type(c_ptr), intent(inout) :: cptr1, cptr2
+    integer(c_size_t), intent(in) :: n
+    integer(c_int), allocatable, intent(out) :: v(:,:)
+    integer(c_size_t), allocatable, intent(out) :: dims(:)
+    integer(c_int), pointer :: v_(:,:)
+    integer(c_size_t), pointer :: dims_(:)
+    type(c_ptr), pointer :: ptrs(:)
+    integer(c_size_t) :: i, istart, iend
+    call c_f_pointer(cptr2, dims_, [n])
+    allocate(dims, source=dims_)
+    allocate(v(2, int(sum(dims_)/2)))
+    istart = 1
+    call c_f_pointer(cptr1, ptrs, [n])
+    do i = 1_c_size_t, n
+        iend = int(dims(i)/2)
+        call c_f_pointer(ptrs(i), v_, [2_c_size_t, iend])
+        v(:,istart:iend) = v_
+        istart = istart + iend
+    end do
+    do i = 1_c_size_t, n
+        call gmshFree(ptrs(i))
+    end do
+    call gmshFree(cptr1)
+    call gmshFree(cptr2)
+  end subroutine ovectorvectorpair_
+
+  !> Calculates the length of a C string.
+  function cstrlen(carray) result(res)
+    character(kind=c_char, len=1), intent(in) :: carray(:)
+    integer :: res
+    integer :: i
+    do i = 1, size(carray)
+      if (carray(i) == c_null_char) then
+        res = i - 1
+        return
+      end if
+    end do
+    res = i
+  end function cstrlen
+
+end module gmsh
diff --git a/api/gmshf.h b/api/gmshf.h
deleted file mode 100644
index 9f982a7f4f2ddc81bb3388b1d76ce6c387cfabc5..0000000000000000000000000000000000000000
--- a/api/gmshf.h
+++ /dev/null
@@ -1,7221 +0,0 @@
-c
-c  Gmsh - Copyright (C) 1997-2022 C. Geuzaine, J.-F. Remacle
-c
-c  See the LICENSE.txt file in the Gmsh root directory for license information.
-c  Please report all issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
-c
-
-!DEC$ IF DEFINED (GMSHF_H)
-!DEC$ ELSE
-!DEC$ DEFINE GMSHF_H
-
-c
-c  This file defines the Gmsh Fortran API (v4.11.0).
-c
-c  Do not edit this file directly: it is automatically generated by `api/gen.py'.
-c
-c  By design, the Gmsh Fortran API is purely functional, and only uses elementary
-c  Fortran types. See `tutorials/fortran' and `examples/api' for tutorials and
-c  examples.
-c
-
-!DEC$ DEFINE GMSH_API_VERSION_MAJOR = 4
-!DEC$ DEFINE GMSH_API_VERSION_MINOR = 11
-!DEC$ DEFINE GMSH_API_VERSION_PATCH = 0
-
-      module gmsh_fortran
-
-        use, intrinsic :: iso_c_binding
-
-        character(len = 5), parameter :: GMSH_API_VERSION = "4.11.0"
-        real(c_double), parameter::M_PI = 3.14159265358979323846d0
-
-        interface
-
-!  Initialize the Gmsh API. This must be called before any call to the other
-!  functions in the API. If `argc' and `argv' (or just `argv' in Python or
-!  Julia) are provided, they will be handled in the same way as the command
-!  line arguments in the Gmsh app. If `readConfigFiles' is set, read system
-!  Gmsh configuration files (gmshrc and gmsh-options). If `run' is set, run in
-!  the same way as the Gmsh app, either interactively or in batch mode
-!  depending on the command line arguments. If `run' is not set, initializing
-!  the API sets the options "General.AbortOnError" to 2 and "General.Terminal"
-!  to 1.
-        subroutine gmshInitialize(
-     &      argc,
-     &      argv,
-     &      readConfigFiles,
-     &      run,
-     &      ierr)
-     &    bind(C, name = "gmshInitialize")
-          use, intrinsic :: iso_c_binding
-            integer (C_INT), value :: argc
-            type (C_PTR)::argv(*)
-            integer(c_int), value::readConfigFiles
-            integer(c_int), value::run
-            integer(c_int)::ierr
-          end subroutine gmshInitialize
-
-!  Return 1 if the Gmsh API is initialized, and 0 if not.
-        function gmshIsInitialized(
-     &      ierr)
-     &    bind(C, name = "gmshIsInitialized")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshIsInitialized
-            integer(c_int)::ierr
-          end function gmshIsInitialized
-
-!  Finalize the Gmsh API. This must be called when you are done using the Gmsh
-!  API.
-        subroutine gmshFinalize(
-     &      ierr)
-     &    bind(C, name = "gmshFinalize")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::ierr
-          end subroutine gmshFinalize
-
-!  Open a file. Equivalent to the `File->Open' menu in the Gmsh app. Handling
-!  of the file depends on its extension and/or its contents: opening a file
-!  with model data will create a new model.
-        subroutine gmshOpen(
-     &      fileName,
-     &      ierr)
-     &    bind(C, name = "gmshOpen")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::fileName(*)
-            integer(c_int)::ierr
-          end subroutine gmshOpen
-
-!  Merge a file. Equivalent to the `File->Merge' menu in the Gmsh app.
-!  Handling of the file depends on its extension and/or its contents. Merging
-!  a file with model data will add the data to the current model.
-        subroutine gmshMerge(
-     &      fileName,
-     &      ierr)
-     &    bind(C, name = "gmshMerge")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::fileName(*)
-            integer(c_int)::ierr
-          end subroutine gmshMerge
-
-!  Write a file. The export format is determined by the file extension.
-        subroutine gmshWrite(
-     &      fileName,
-     &      ierr)
-     &    bind(C, name = "gmshWrite")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::fileName(*)
-            integer(c_int)::ierr
-          end subroutine gmshWrite
-
-!  Clear all loaded models and post-processing data, and add a new empty
-!  model.
-        subroutine gmshClear(
-     &      ierr)
-     &    bind(C, name = "gmshClear")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::ierr
-          end subroutine gmshClear
-
-!  Set 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.
-        subroutine gmshOptionSetNumber(
-     &      name,
-     &      value,
-     &      ierr)
-     &    bind(C, name = "gmshOptionSetNumber")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::name(*)
-            real(c_double), value::value
-            integer(c_int)::ierr
-          end subroutine gmshOptionSetNumber
-
-!  Get the `value' of a numerical option. `name' is of the form
-!  "Category.Option" or "Category[num].Option". Available categories and
-!  options are listed in the Gmsh reference manual.
-        subroutine gmshOptionGetNumber(
-     &      name,
-     &      value,
-     &      ierr)
-     &    bind(C, name = "gmshOptionGetNumber")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::name(*)
-            real(c_double)::value
-            integer(c_int)::ierr
-          end subroutine gmshOptionGetNumber
-
-!  Set a string 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.
-        subroutine gmshOptionSetString(
-     &      name,
-     &      value,
-     &      ierr)
-     &    bind(C, name = "gmshOptionSetString")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::name(*)
-            character(len = 1, kind = c_char)::value(*)
-            integer(c_int)::ierr
-          end subroutine gmshOptionSetString
-
-!  Get the `value' of a string option. `name' is of the form "Category.Option"
-!  or "Category[num].Option". Available categories and options are listed in
-!  the Gmsh reference manual.
-        subroutine gmshOptionGetString(
-     &      name,
-     &      value,
-     &      ierr)
-     &    bind(C, name = "gmshOptionGetString")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::name(*)
-            type(c_ptr)::value(*)
-            integer(c_int)::ierr
-          end subroutine gmshOptionGetString
-
-!  Set a color option to the RGBA value (`r', `g', `b', `a'), where where `r',
-!  `g', `b' and `a' should be integers between 0 and 255. `name' is of the
-!  form "Category.Color.Option" or "Category[num].Color.Option". Available
-!  categories and options are listed in the Gmsh reference manual. For
-!  conciseness "Color." can be ommitted in `name'.
-        subroutine gmshOptionSetColor(
-     &      name,
-     &      r,
-     &      g,
-     &      b,
-     &      a,
-     &      ierr)
-     &    bind(C, name = "gmshOptionSetColor")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::name(*)
-            integer(c_int), value::r
-            integer(c_int), value::g
-            integer(c_int), value::b
-            integer(c_int), value::a
-            integer(c_int)::ierr
-          end subroutine gmshOptionSetColor
-
-!  Get the `r', `g', `b', `a' value of a color option. `name' is of the form
-!  "Category.Color.Option" or "Category[num].Color.Option". Available
-!  categories and options are listed in the Gmsh reference manual. For
-!  conciseness "Color." can be ommitted in `name'.
-        subroutine gmshOptionGetColor(
-     &      name,
-     &      r,
-     &      g,
-     &      b,
-     &      a,
-     &      ierr)
-     &    bind(C, name = "gmshOptionGetColor")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::name(*)
-            integer(c_int)::r
-            integer(c_int)::g
-            integer(c_int)::b
-            integer(c_int)::a
-            integer(c_int)::ierr
-          end subroutine gmshOptionGetColor
-
-!  Add a new model, with name `name', and set it as the current model.
-        subroutine gmshModelAdd(
-     &      name,
-     &      ierr)
-     &    bind(C, name = "gmshModelAdd")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::name(*)
-            integer(c_int)::ierr
-          end subroutine gmshModelAdd
-
-!  Remove the current model.
-        subroutine gmshModelRemove(
-     &      ierr)
-     &    bind(C, name = "gmshModelRemove")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::ierr
-          end subroutine gmshModelRemove
-
-!  List the names of all models.
-        subroutine gmshModelList(
-     &      names,
-     &      names_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelList")
-          use, intrinsic :: iso_c_binding
-            type(c_ptr), intent(out)::names
-            integer(c_size_t) :: names_n
-            integer(c_int)::ierr
-          end subroutine gmshModelList
-
-!  Get the name of the current model.
-        subroutine gmshModelGetCurrent(
-     &      name,
-     &      ierr)
-     &    bind(C, name = "gmshModelGetCurrent")
-          use, intrinsic :: iso_c_binding
-            type(c_ptr)::name(*)
-            integer(c_int)::ierr
-          end subroutine gmshModelGetCurrent
-
-!  Set the current model to the model with name `name'. If several models have
-!  the same name, select the one that was added first.
-        subroutine gmshModelSetCurrent(
-     &      name,
-     &      ierr)
-     &    bind(C, name = "gmshModelSetCurrent")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::name(*)
-            integer(c_int)::ierr
-          end subroutine gmshModelSetCurrent
-
-!  Get the file name (if any) associated with the current model. A file name
-!  is associated when a model is read from a file on disk.
-        subroutine gmshModelGetFileName(
-     &      fileName,
-     &      ierr)
-     &    bind(C, name = "gmshModelGetFileName")
-          use, intrinsic :: iso_c_binding
-            type(c_ptr)::fileName(*)
-            integer(c_int)::ierr
-          end subroutine gmshModelGetFileName
-
-!  Set the file name associated with the current model.
-        subroutine gmshModelSetFileName(
-     &      fileName,
-     &      ierr)
-     &    bind(C, name = "gmshModelSetFileName")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::fileName(*)
-            integer(c_int)::ierr
-          end subroutine gmshModelSetFileName
-
-!  Get all the entities in the current model. If `dim' is >= 0, return 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.
-        subroutine gmshModelGetEntities(
-     &      dimTags,
-     &      dimTags_n,
-     &      dim,
-     &      ierr)
-     &    bind(C, name = "gmshModelGetEntities")
-          use, intrinsic :: iso_c_binding
-            type(c_ptr), intent(out)::dimTags
-            integer(c_size_t) :: dimTags_n
-            integer(c_int), value::dim
-            integer(c_int)::ierr
-          end subroutine gmshModelGetEntities
-
-!  Set the name of the entity of dimension `dim' and tag `tag'.
-        subroutine gmshModelSetEntityName(
-     &      dim,
-     &      tag,
-     &      name,
-     &      ierr)
-     &    bind(C, name = "gmshModelSetEntityName")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            character(len = 1, kind = c_char)::name(*)
-            integer(c_int)::ierr
-          end subroutine gmshModelSetEntityName
-
-!  Get the name of the entity of dimension `dim' and tag `tag'.
-        subroutine gmshModelGetEntityName(
-     &      dim,
-     &      tag,
-     &      name,
-     &      ierr)
-     &    bind(C, name = "gmshModelGetEntityName")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            type(c_ptr)::name(*)
-            integer(c_int)::ierr
-          end subroutine gmshModelGetEntityName
-
-!  Get all the physical groups in the current model. If `dim' is >= 0, return
-!  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.
-        subroutine gmshModelGetPhysicalGroups(
-     &      dimTags,
-     &      dimTags_n,
-     &      dim,
-     &      ierr)
-     &    bind(C, name = "gmshModelGetPhysicalGroups")
-          use, intrinsic :: iso_c_binding
-            type(c_ptr), intent(out)::dimTags
-            integer(c_size_t) :: dimTags_n
-            integer(c_int), value::dim
-            integer(c_int)::ierr
-          end subroutine gmshModelGetPhysicalGroups
-
-!  Get the tags of the model entities making up the physical group of
-!  dimension `dim' and tag `tag'.
-        subroutine gmshModelGetEntitiesForPhysicalGroup(
-     &      dim,
-     &      tag,
-     &      tags,
-     &      tags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelGetEntitiesForPhysicalGroup")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            type(c_ptr), intent(out)::tags
-            integer(c_size_t) :: tags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelGetEntitiesForPhysicalGroup
-
-!  Get the tags of the physical groups (if any) to which the model entity of
-!  dimension `dim' and tag `tag' belongs.
-        subroutine gmshModelGetPhysicalGroupsForEntity(
-     &      dim,
-     &      tag,
-     &      physicalTags,
-     &      physicalTags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelGetPhysicalGroupsForEntity")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            type(c_ptr), intent(out)::physicalTags
-            integer(c_size_t) :: physicalTags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelGetPhysicalGroupsForEntity
-
-!  Add a physical group of dimension `dim', grouping the model entities with
-!  tags `tags'. Return the tag of the physical group, equal to `tag' if `tag'
-!  is positive, or a new tag if `tag' < 0. Set the name of the physical group
-!  if `name' is not empty.
-        function gmshModelAddPhysicalGroup(
-     &      dim,
-     &      tags,
-     &      tags_n,
-     &      tag,
-     &      name,
-     &      ierr)
-     &    bind(C, name = "gmshModelAddPhysicalGroup")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelAddPhysicalGroup
-            integer(c_int), value::dim
-            integer(c_int)::tags(*)
-            integer(c_size_t), value :: tags_n
-            integer(c_int), value::tag
-            character(len = 1, kind = c_char)::name(*)
-            integer(c_int)::ierr
-          end function gmshModelAddPhysicalGroup
-
-!  Remove the physical groups `dimTags' from the current model. If `dimTags'
-!  is empty, remove all groups.
-        subroutine gmshModelRemovePhysicalGroups(
-     &      dimTags,
-     &      dimTags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelRemovePhysicalGroups")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelRemovePhysicalGroups
-
-!  Set the name of the physical group of dimension `dim' and tag `tag'.
-        subroutine gmshModelSetPhysicalName(
-     &      dim,
-     &      tag,
-     &      name,
-     &      ierr)
-     &    bind(C, name = "gmshModelSetPhysicalName")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            character(len = 1, kind = c_char)::name(*)
-            integer(c_int)::ierr
-          end subroutine gmshModelSetPhysicalName
-
-!  Remove the physical name `name' from the current model.
-        subroutine gmshModelRemovePhysicalName(
-     &      name,
-     &      ierr)
-     &    bind(C, name = "gmshModelRemovePhysicalName")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::name(*)
-            integer(c_int)::ierr
-          end subroutine gmshModelRemovePhysicalName
-
-!  Get the name of the physical group of dimension `dim' and tag `tag'.
-        subroutine gmshModelGetPhysicalName(
-     &      dim,
-     &      tag,
-     &      name,
-     &      ierr)
-     &    bind(C, name = "gmshModelGetPhysicalName")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            type(c_ptr)::name(*)
-            integer(c_int)::ierr
-          end subroutine gmshModelGetPhysicalName
-
-!  Set the tag of the entity of dimension `dim' and tag `tag' to the new value
-!  `newTag'.
-        subroutine gmshModelSetTag(
-     &      dim,
-     &      tag,
-     &      newTag,
-     &      ierr)
-     &    bind(C, name = "gmshModelSetTag")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            integer(c_int), value::newTag
-            integer(c_int)::ierr
-          end subroutine gmshModelSetTag
-
-!  Get the boundary of the model entities `dimTags'. Return 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). Return tags multiplied by the sign of the boundary
-!  entity if `oriented' is true. Apply the boundary operator recursively down
-!  to dimension 0 (i.e. to points) if `recursive' is true.
-        subroutine gmshModelGetBoundary(
-     &      dimTags,
-     &      dimTags_n,
-     &      outDimTags,
-     &      outDimTags_n,
-     &      combined,
-     &      oriented,
-     &      recursive,
-     &      ierr)
-     &    bind(C, name = "gmshModelGetBoundary")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            type(c_ptr), intent(out)::outDimTags
-            integer(c_size_t) :: outDimTags_n
-            integer(c_int), value::combined
-            integer(c_int), value::oriented
-            integer(c_int), value::recursive
-            integer(c_int)::ierr
-          end subroutine gmshModelGetBoundary
-
-!  Get the upward and downward adjacencies of the model entity of dimension
-!  `dim' and tag `tag'. The `upward' vector returns the adjacent entities of
-!  dimension `dim' + 1; the `downward' vector returns the adjacent entities of
-!  dimension `dim' - 1.
-        subroutine gmshModelGetAdjacencies(
-     &      dim,
-     &      tag,
-     &      upward,
-     &      upward_n,
-     &      downward,
-     &      downward_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelGetAdjacencies")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            type(c_ptr), intent(out)::upward
-            integer(c_size_t) :: upward_n
-            type(c_ptr), intent(out)::downward
-            integer(c_size_t) :: downward_n
-            integer(c_int)::ierr
-          end subroutine gmshModelGetAdjacencies
-
-!  Get the model entities in the bounding box defined by the two points
-!  (`xmin', `ymin', `zmin') and (`xmax', `ymax', `zmax'). If `dim' is >= 0,
-!  return only the entities of the specified dimension (e.g. points if `dim'
-!  == 0).
-        subroutine gmshModelGetEntitiesInBoundingBox(
-     &      xmin,
-     &      ymin,
-     &      zmin,
-     &      xmax,
-     &      ymax,
-     &      zmax,
-     &      tags,
-     &      tags_n,
-     &      dim,
-     &      ierr)
-     &    bind(C, name = "gmshModelGetEntitiesInBoundingBox")
-          use, intrinsic :: iso_c_binding
-            real(c_double), value::xmin
-            real(c_double), value::ymin
-            real(c_double), value::zmin
-            real(c_double), value::xmax
-            real(c_double), value::ymax
-            real(c_double), value::zmax
-            type(c_ptr), intent(out)::tags
-            integer(c_size_t) :: tags_n
-            integer(c_int), value::dim
-            integer(c_int)::ierr
-          end subroutine gmshModelGetEntitiesInBoundingBox
-
-!  Get the bounding box (`xmin', `ymin', `zmin'), (`xmax', `ymax', `zmax') of
-!  the model entity of dimension `dim' and tag `tag'. If `dim' and `tag' are
-!  negative, get the bounding box of the whole model.
-        subroutine gmshModelGetBoundingBox(
-     &      dim,
-     &      tag,
-     &      xmin,
-     &      ymin,
-     &      zmin,
-     &      xmax,
-     &      ymax,
-     &      zmax,
-     &      ierr)
-     &    bind(C, name = "gmshModelGetBoundingBox")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            real(c_double)::xmin
-            real(c_double)::ymin
-            real(c_double)::zmin
-            real(c_double)::xmax
-            real(c_double)::ymax
-            real(c_double)::zmax
-            integer(c_int)::ierr
-          end subroutine gmshModelGetBoundingBox
-
-!  Return the geometrical dimension of the current model.
-        function gmshModelGetDimension(
-     &      ierr)
-     &    bind(C, name = "gmshModelGetDimension")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelGetDimension
-            integer(c_int)::ierr
-          end function gmshModelGetDimension
-
-!  Add a discrete model entity (defined by a mesh) of dimension `dim' in the
-!  current model. Return 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. Specifying
-!  `boundary' allows Gmsh to construct the topology of the overall model.
-        function gmshModelAddDiscreteEntity(
-     &      dim,
-     &      tag,
-     &      boundary,
-     &      boundary_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelAddDiscreteEntity")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelAddDiscreteEntity
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            integer(c_int)::boundary(*)
-            integer(c_size_t), value :: boundary_n
-            integer(c_int)::ierr
-          end function gmshModelAddDiscreteEntity
-
-!  Remove the entities `dimTags' of the current model, provided that they are
-!  not on the boundary of (or embedded in) higher-dimensional entities. If
-!  `recursive' is true, remove all the entities on their boundaries, down to
-!  dimension 0.
-        subroutine gmshModelRemoveEntities(
-     &      dimTags,
-     &      dimTags_n,
-     &      recursive,
-     &      ierr)
-     &    bind(C, name = "gmshModelRemoveEntities")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            integer(c_int), value::recursive
-            integer(c_int)::ierr
-          end subroutine gmshModelRemoveEntities
-
-!  Remove the entity name `name' from the current model.
-        subroutine gmshModelRemoveEntityName(
-     &      name,
-     &      ierr)
-     &    bind(C, name = "gmshModelRemoveEntityName")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::name(*)
-            integer(c_int)::ierr
-          end subroutine gmshModelRemoveEntityName
-
-!  Get the type of the entity of dimension `dim' and tag `tag'.
-        subroutine gmshModelGetType(
-     &      dim,
-     &      tag,
-     &      entityType,
-     &      ierr)
-     &    bind(C, name = "gmshModelGetType")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            type(c_ptr)::entityType(*)
-            integer(c_int)::ierr
-          end subroutine gmshModelGetType
-
-!  In a partitioned model, get the parent of the entity of dimension `dim' and
-!  tag `tag', i.e. from which the entity is a part of, if any. `parentDim' and
-!  `parentTag' are set to -1 if the entity has no parent.
-        subroutine gmshModelGetParent(
-     &      dim,
-     &      tag,
-     &      parentDim,
-     &      parentTag,
-     &      ierr)
-     &    bind(C, name = "gmshModelGetParent")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            integer(c_int)::parentDim
-            integer(c_int)::parentTag
-            integer(c_int)::ierr
-          end subroutine gmshModelGetParent
-
-!  Return the number of partitions in the model.
-        function gmshModelGetNumberOfPartitions(
-     &      ierr)
-     &    bind(C, name = "gmshModelGetNumberOfPartitions")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelGetNumberOfPartitions
-            integer(c_int)::ierr
-          end function gmshModelGetNumberOfPartitions
-
-!  In a partitioned model, return the tags of the partition(s) to which the
-!  entity belongs.
-        subroutine gmshModelGetPartitions(
-     &      dim,
-     &      tag,
-     &      partitions,
-     &      partitions_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelGetPartitions")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            type(c_ptr), intent(out)::partitions
-            integer(c_size_t) :: partitions_n
-            integer(c_int)::ierr
-          end subroutine gmshModelGetPartitions
-
-!  Evaluate the parametrization of the entity of dimension `dim' and tag `tag'
-!  at the parametric coordinates `parametricCoord'. Only valid for `dim' equal
-!  to 0 (with empty `parametricCoord'), 1 (with `parametricCoord' containing
-!  parametric coordinates on the curve) or 2 (with `parametricCoord'
-!  containing pairs of u, v parametric coordinates on the surface,
-!  concatenated: [p1u, p1v, p2u, ...]). Return triplets of x, y, z coordinates
-!  in `coord', concatenated: [p1x, p1y, p1z, p2x, ...].
-        subroutine gmshModelGetValue(
-     &      dim,
-     &      tag,
-     &      parametricCoord,
-     &      parametricCoord_n,
-     &      coord,
-     &      coord_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelGetValue")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            real(c_double)::parametricCoord(*)
-            integer(c_size_t), value :: parametricCoord_n
-            type(c_ptr), intent(out)::coord
-            integer(c_size_t) :: coord_n
-            integer(c_int)::ierr
-          end subroutine gmshModelGetValue
-
-!  Evaluate the derivative of the parametrization of the entity of dimension
-!  `dim' and tag `tag' at the parametric coordinates `parametricCoord'. Only
-!  valid for `dim' equal to 1 (with `parametricCoord' containing parametric
-!  coordinates on the curve) or 2 (with `parametricCoord' containing pairs of
-!  u, v parametric coordinates on the surface, concatenated: [p1u, p1v, p2u,
-!  ...]). For `dim' equal to 1 return the x, y, z components of the derivative
-!  with respect to u [d1ux, d1uy, d1uz, d2ux, ...]; for `dim' equal to 2
-!  return the x, y, z components of the derivative with respect to u and v:
-!  [d1ux, d1uy, d1uz, d1vx, d1vy, d1vz, d2ux, ...].
-        subroutine gmshModelGetDerivative(
-     &      dim,
-     &      tag,
-     &      parametricCoord,
-     &      parametricCoord_n,
-     &      derivatives,
-     &      derivatives_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelGetDerivative")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            real(c_double)::parametricCoord(*)
-            integer(c_size_t), value :: parametricCoord_n
-            type(c_ptr), intent(out)::derivatives
-            integer(c_size_t) :: derivatives_n
-            integer(c_int)::ierr
-          end subroutine gmshModelGetDerivative
-
-!  Evaluate the second derivative of the parametrization of the entity of
-!  dimension `dim' and tag `tag' at the parametric coordinates
-!  `parametricCoord'. Only valid for `dim' equal to 1 (with `parametricCoord'
-!  containing parametric coordinates on the curve) or 2 (with
-!  `parametricCoord' containing pairs of u, v parametric coordinates on the
-!  surface, concatenated: [p1u, p1v, p2u, ...]). For `dim' equal to 1 return
-!  the x, y, z components of the second derivative with respect to u [d1uux,
-!  d1uuy, d1uuz, d2uux, ...]; for `dim' equal to 2 return the x, y, z
-!  components of the second derivative with respect to u and v, and the mixed
-!  derivative with respect to u and v: [d1uux, d1uuy, d1uuz, d1vvx, d1vvy,
-!  d1vvz, d1uvx, d1uvy, d1uvz, d2uux, ...].
-        subroutine gmshModelGetSecondDerivative(
-     &      dim,
-     &      tag,
-     &      parametricCoord,
-     &      parametricCoord_n,
-     &      derivatives,
-     &      derivatives_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelGetSecondDerivative")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            real(c_double)::parametricCoord(*)
-            integer(c_size_t), value :: parametricCoord_n
-            type(c_ptr), intent(out)::derivatives
-            integer(c_size_t) :: derivatives_n
-            integer(c_int)::ierr
-          end subroutine gmshModelGetSecondDerivative
-
-!  Evaluate the (maximum) curvature of the entity of dimension `dim' and tag
-!  `tag' at the parametric coordinates `parametricCoord'. Only valid for `dim'
-!  equal to 1 (with `parametricCoord' containing parametric coordinates on the
-!  curve) or 2 (with `parametricCoord' containing pairs of u, v parametric
-!  coordinates on the surface, concatenated: [p1u, p1v, p2u, ...]).
-        subroutine gmshModelGetCurvature(
-     &      dim,
-     &      tag,
-     &      parametricCoord,
-     &      parametricCoord_n,
-     &      curvatures,
-     &      curvatures_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelGetCurvature")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            real(c_double)::parametricCoord(*)
-            integer(c_size_t), value :: parametricCoord_n
-            type(c_ptr), intent(out)::curvatures
-            integer(c_size_t) :: curvatures_n
-            integer(c_int)::ierr
-          end subroutine gmshModelGetCurvature
-
-!  Evaluate the principal curvatures of the surface with tag `tag' at the
-!  parametric coordinates `parametricCoord', as well as their respective
-!  directions. `parametricCoord' are given by pair of u and v coordinates,
-!  concatenated: [p1u, p1v, p2u, ...].
-        subroutine gmshModelGetPrincipalCurvatures(
-     &      tag,
-     &      parametricCoord,
-     &      parametricCoord_n,
-     &      curvatureMax,
-     &      curvatureMax_n,
-     &      curvatureMin,
-     &      curvatureMin_n,
-     &      directionMax,
-     &      directionMax_n,
-     &      directionMin,
-     &      directionMin_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelGetPrincipalCurvatures")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            real(c_double)::parametricCoord(*)
-            integer(c_size_t), value :: parametricCoord_n
-            type(c_ptr), intent(out)::curvatureMax
-            integer(c_size_t) :: curvatureMax_n
-            type(c_ptr), intent(out)::curvatureMin
-            integer(c_size_t) :: curvatureMin_n
-            type(c_ptr), intent(out)::directionMax
-            integer(c_size_t) :: directionMax_n
-            type(c_ptr), intent(out)::directionMin
-            integer(c_size_t) :: directionMin_n
-            integer(c_int)::ierr
-          end subroutine gmshModelGetPrincipalCurvatures
-
-!  Get the normal to the surface with tag `tag' at the parametric coordinates
-!  `parametricCoord'. `parametricCoord' are given by pairs of u and v
-!  coordinates, concatenated: [p1u, p1v, p2u, ...]. `normals' are returned as
-!  triplets of x, y, z components, concatenated: [n1x, n1y, n1z, n2x, ...].
-        subroutine gmshModelGetNormal(
-     &      tag,
-     &      parametricCoord,
-     &      parametricCoord_n,
-     &      normals,
-     &      normals_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelGetNormal")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            real(c_double)::parametricCoord(*)
-            integer(c_size_t), value :: parametricCoord_n
-            type(c_ptr), intent(out)::normals
-            integer(c_size_t) :: normals_n
-            integer(c_int)::ierr
-          end subroutine gmshModelGetNormal
-
-!  Get the parametric coordinates `parametricCoord' for the points `coord' on
-!  the entity of dimension `dim' and tag `tag'. `coord' are given as triplets
-!  of x, y, z coordinates, concatenated: [p1x, p1y, p1z, p2x, ...].
-!  `parametricCoord' returns the parametric coordinates t on the curve (if
-!  `dim' = 1) or pairs of u and v coordinates concatenated on the surface (if
-!  `dim' = 2), i.e. [p1t, p2t, ...] or [p1u, p1v, p2u, ...].
-        subroutine gmshModelGetParametrization(
-     &      dim,
-     &      tag,
-     &      coord,
-     &      coord_n,
-     &      parametricCoord,
-     &      parametricCoord_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelGetParametrization")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            real(c_double)::coord(*)
-            integer(c_size_t), value :: coord_n
-            type(c_ptr), intent(out)::parametricCoord
-            integer(c_size_t) :: parametricCoord_n
-            integer(c_int)::ierr
-          end subroutine gmshModelGetParametrization
-
-!  Get the `min' and `max' bounds of the parametric coordinates for the entity
-!  of dimension `dim' and tag `tag'.
-        subroutine gmshModelGetParametrizationBounds(
-     &      dim,
-     &      tag,
-     &      min,
-     &      min_n,
-     &      max,
-     &      max_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelGetParametrizationBounds")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            type(c_ptr), intent(out)::min
-            integer(c_size_t) :: min_n
-            type(c_ptr), intent(out)::max
-            integer(c_size_t) :: max_n
-            integer(c_int)::ierr
-          end subroutine gmshModelGetParametrizationBounds
-
-!  Check if the coordinates (or the parametric coordinates if `parametric' is
-!  set) provided in `coord' correspond to points inside the entity of
-!  dimension `dim' and tag `tag', and return the number of points inside. This
-!  feature is only available for a subset of entities, depending on the
-!  underlying geometrical representation.
-        function gmshModelIsInside(
-     &      dim,
-     &      tag,
-     &      coord,
-     &      coord_n,
-     &      parametric,
-     &      ierr)
-     &    bind(C, name = "gmshModelIsInside")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelIsInside
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            real(c_double)::coord(*)
-            integer(c_size_t), value :: coord_n
-            integer(c_int), value::parametric
-            integer(c_int)::ierr
-          end function gmshModelIsInside
-
-!  Get the points `closestCoord' on the entity of dimension `dim' and tag
-!  `tag' to the points `coord', by orthogonal projection. `coord' and
-!  `closestCoord' are given as triplets of x, y, z coordinates, concatenated:
-!  [p1x, p1y, p1z, p2x, ...]. `parametricCoord' returns the parametric
-!  coordinates t on the curve (if `dim' = 1) or pairs of u and v coordinates
-!  concatenated on the surface (if `dim' = 2), i.e. [p1t, p2t, ...] or [p1u,
-!  p1v, p2u, ...].
-        subroutine gmshModelGetClosestPoint(
-     &      dim,
-     &      tag,
-     &      coord,
-     &      coord_n,
-     &      closestCoord,
-     &      closestCoord_n,
-     &      parametricCoord,
-     &      parametricCoord_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelGetClosestPoint")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            real(c_double)::coord(*)
-            integer(c_size_t), value :: coord_n
-            type(c_ptr), intent(out)::closestCoord
-            integer(c_size_t) :: closestCoord_n
-            type(c_ptr), intent(out)::parametricCoord
-            integer(c_size_t) :: parametricCoord_n
-            integer(c_int)::ierr
-          end subroutine gmshModelGetClosestPoint
-
-!  Reparametrize the boundary entity (point or curve, i.e. with `dim' == 0 or
-!  `dim' == 1) of tag `tag' on the surface `surfaceTag'. If `dim' == 1,
-!  reparametrize all the points corresponding to the parametric coordinates
-!  `parametricCoord'. Multiple matches in case of periodic surfaces can be
-!  selected with `which'. This feature is only available for a subset of
-!  entities, depending on the underlying geometrical representation.
-        subroutine gmshModelReparametrizeOnSurface(
-     &      dim,
-     &      tag,
-     &      parametricCoord,
-     &      parametricCoord_n,
-     &      surfaceTag,
-     &      surfaceParametricCoord,
-     &      surfaceParametricCoord_n,
-     &      which,
-     &      ierr)
-     &    bind(C, name = "gmshModelReparametrizeOnSurface")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            real(c_double)::parametricCoord(*)
-            integer(c_size_t), value :: parametricCoord_n
-            integer(c_int), value::surfaceTag
-            type(c_ptr), intent(out)::surfaceParametricCoord
-            integer(c_size_t) :: surfaceParametricCoord_n
-            integer(c_int), value::which
-            integer(c_int)::ierr
-          end subroutine gmshModelReparametrizeOnSurface
-
-!  Set the visibility of the model entities `dimTags' to `value'. Apply the
-!  visibility setting recursively if `recursive' is true.
-        subroutine gmshModelSetVisibility(
-     &      dimTags,
-     &      dimTags_n,
-     &      value,
-     &      recursive,
-     &      ierr)
-     &    bind(C, name = "gmshModelSetVisibility")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            integer(c_int), value::value
-            integer(c_int), value::recursive
-            integer(c_int)::ierr
-          end subroutine gmshModelSetVisibility
-
-!  Get the visibility of the model entity of dimension `dim' and tag `tag'.
-        subroutine gmshModelGetVisibility(
-     &      dim,
-     &      tag,
-     &      value,
-     &      ierr)
-     &    bind(C, name = "gmshModelGetVisibility")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            integer(c_int)::value
-            integer(c_int)::ierr
-          end subroutine gmshModelGetVisibility
-
-!  Set the global visibility of the model per window to `value', where
-!  `windowIndex' identifies the window in the window list.
-        subroutine gmshModelSetVisibilityPerWindow(
-     &      value,
-     &      windowIndex,
-     &      ierr)
-     &    bind(C, name = "gmshModelSetVisibilityPerWindow")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::value
-            integer(c_int), value::windowIndex
-            integer(c_int)::ierr
-          end subroutine gmshModelSetVisibilityPerWindow
-
-!  Set the color of the model entities `dimTags' to the RGBA value (`r', `g',
-!  `b', `a'), where `r', `g', `b' and `a' should be integers between 0 and
-!  255. Apply the color setting recursively if `recursive' is true.
-        subroutine gmshModelSetColor(
-     &      dimTags,
-     &      dimTags_n,
-     &      r,
-     &      g,
-     &      b,
-     &      a,
-     &      recursive,
-     &      ierr)
-     &    bind(C, name = "gmshModelSetColor")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            integer(c_int), value::r
-            integer(c_int), value::g
-            integer(c_int), value::b
-            integer(c_int), value::a
-            integer(c_int), value::recursive
-            integer(c_int)::ierr
-          end subroutine gmshModelSetColor
-
-!  Get the color of the model entity of dimension `dim' and tag `tag'.
-        subroutine gmshModelGetColor(
-     &      dim,
-     &      tag,
-     &      r,
-     &      g,
-     &      b,
-     &      a,
-     &      ierr)
-     &    bind(C, name = "gmshModelGetColor")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            integer(c_int)::r
-            integer(c_int)::g
-            integer(c_int)::b
-            integer(c_int)::a
-            integer(c_int)::ierr
-          end subroutine gmshModelGetColor
-
-!  Set the `x', `y', `z' coordinates of a geometrical point.
-        subroutine gmshModelSetCoordinates(
-     &      tag,
-     &      x,
-     &      y,
-     &      z,
-     &      ierr)
-     &    bind(C, name = "gmshModelSetCoordinates")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            real(c_double), value::x
-            real(c_double), value::y
-            real(c_double), value::z
-            integer(c_int)::ierr
-          end subroutine gmshModelSetCoordinates
-
-!  Get the names of any optional attributes stored in the model.
-        subroutine gmshModelGetAttributeNames(
-     &      names,
-     &      names_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelGetAttributeNames")
-          use, intrinsic :: iso_c_binding
-            type(c_ptr), intent(out)::names
-            integer(c_size_t) :: names_n
-            integer(c_int)::ierr
-          end subroutine gmshModelGetAttributeNames
-
-!  Get the value of the attribute with name `name'.
-        subroutine gmshModelGetAttribute(
-     &      name,
-     &      value,
-     &      value_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelGetAttribute")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::name(*)
-            type(c_ptr), intent(out)::value
-            integer(c_size_t) :: value_n
-            integer(c_int)::ierr
-          end subroutine gmshModelGetAttribute
-
-!  Set the value of the attribute with name `name'.
-        subroutine gmshModelSetAttribute(
-     &      name,
-     &      value,
-     &      value_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelSetAttribute")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::name(*)
-            type(c_ptr)::value(*)
-            integer(c_size_t), value :: value_n
-            integer(c_int)::ierr
-          end subroutine gmshModelSetAttribute
-
-!  Remove the attribute with name `name'.
-        subroutine gmshModelRemoveAttribute(
-     &      name,
-     &      ierr)
-     &    bind(C, name = "gmshModelRemoveAttribute")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::name(*)
-            integer(c_int)::ierr
-          end subroutine gmshModelRemoveAttribute
-
-!  Generate a mesh of the current model, up to dimension `dim' (0, 1, 2 or 3).
-        subroutine gmshModelMeshGenerate(
-     &      dim,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGenerate")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGenerate
-
-!  Partition the mesh of the current model into `numPart' partitions.
-!  Optionally, `elementTags' and `partitions' can be provided to specify the
-!  partition of each element explicitly.
-        subroutine gmshModelMeshPartition(
-     &      numPart,
-     &      elementTags,
-     &      elementTags_n,
-     &      partitions,
-     &      partitions_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshPartition")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::numPart
-            integer(c_size_t)::elementTags(*)
-            integer(c_size_t), value :: elementTags_n
-            integer(c_int)::partitions(*)
-            integer(c_size_t), value :: partitions_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshPartition
-
-!  Unpartition the mesh of the current model.
-        subroutine gmshModelMeshUnpartition(
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshUnpartition")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshUnpartition
-
-!  Optimize the mesh of the current model using `method' (empty for default
-!  tetrahedral mesh optimizer, "Netgen" for Netgen optimizer, "HighOrder" for
-!  direct high-order mesh optimizer, "HighOrderElastic" for high-order elastic
-!  smoother, "HighOrderFastCurving" for fast curving algorithm, "Laplace2D"
-!  for Laplace smoothing, "Relocate2D" and "Relocate3D" for node relocation,
-!  "QuadQuasiStructured" for quad mesh optimization, "UntangleMeshGeometry"
-!  for untangling). If `force' is set apply the optimization also to discrete
-!  entities. If `dimTags' is given, only apply the optimizer to the given
-!  entities.
-        subroutine gmshModelMeshOptimize(
-     &      method,
-     &      force,
-     &      niter,
-     &      dimTags,
-     &      dimTags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshOptimize")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::method(*)
-            integer(c_int), value::force
-            integer(c_int), value::niter
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshOptimize
-
-!  Recombine the mesh of the current model.
-        subroutine gmshModelMeshRecombine(
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshRecombine")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshRecombine
-
-!  Refine the mesh of the current model by uniformly splitting the elements.
-        subroutine gmshModelMeshRefine(
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshRefine")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshRefine
-
-!  Set the order of the elements in the mesh of the current model to `order'.
-        subroutine gmshModelMeshSetOrder(
-     &      order,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshSetOrder")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::order
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshSetOrder
-
-!  Get the last entities (if any) where a meshing error occurred. Currently
-!  only populated by the new 3D meshing algorithms.
-        subroutine gmshModelMeshGetLastEntityError(
-     &      dimTags,
-     &      dimTags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetLastEntityError")
-          use, intrinsic :: iso_c_binding
-            type(c_ptr), intent(out)::dimTags
-            integer(c_size_t) :: dimTags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetLastEntityError
-
-!  Get the last nodes (if any) where a meshing error occurred. Currently only
-!  populated by the new 3D meshing algorithms.
-        subroutine gmshModelMeshGetLastNodeError(
-     &      nodeTags,
-     &      nodeTags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetLastNodeError")
-          use, intrinsic :: iso_c_binding
-            type(c_ptr), intent(out)::nodeTags
-            integer(c_size_t) :: nodeTags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetLastNodeError
-
-!  Clear the mesh, i.e. delete all the nodes and elements, for the entities
-!  `dimTags'. If `dimTags' is empty, clear the whole mesh. Note that the mesh
-!  of an entity can only be cleared if this entity is not on the boundary of
-!  another entity with a non-empty mesh.
-        subroutine gmshModelMeshClear(
-     &      dimTags,
-     &      dimTags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshClear")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshClear
-
-!  Reverse the orientation of the elements in the entities `dimTags'. If
-!  `dimTags' is empty, reverse the orientation of the elements in the whole
-!  mesh.
-        subroutine gmshModelMeshReverse(
-     &      dimTags,
-     &      dimTags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshReverse")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshReverse
-
-!  Apply the affine transformation `affineTransform' (16 entries of a 4x4
-!  matrix, by row; only the 12 first can be provided for convenience) to the
-!  coordinates of the nodes classified on the entities `dimTags'. If `dimTags'
-!  is empty, transform all the nodes in the mesh.
-        subroutine gmshModelMeshAffineTransform(
-     &      affineTransform,
-     &      affineTransform_n,
-     &      dimTags,
-     &      dimTags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshAffineTransform")
-          use, intrinsic :: iso_c_binding
-            real(c_double)::affineTransform(*)
-            integer(c_size_t), value :: affineTransform_n
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshAffineTransform
-
-!  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).
-        subroutine gmshModelMeshGetNodes(
-     &      nodeTags,
-     &      nodeTags_n,
-     &      coord,
-     &      coord_n,
-     &      parametricCoord,
-     &      parametricCoord_n,
-     &      dim,
-     &      tag,
-     &      includeBoundary,
-     &      returnParametricCoord,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetNodes")
-          use, intrinsic :: iso_c_binding
-            type(c_ptr), intent(out)::nodeTags
-            integer(c_size_t) :: nodeTags_n
-            type(c_ptr), intent(out)::coord
-            integer(c_size_t) :: coord_n
-            type(c_ptr), intent(out)::parametricCoord
-            integer(c_size_t) :: parametricCoord_n
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            integer(c_int), value::includeBoundary
-            integer(c_int), value::returnParametricCoord
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetNodes
-
-!  Get the nodes classified on the entity of tag `tag', for all the elements
-!  of type `elementType'. The other arguments are treated as in `getNodes'.
-        subroutine gmshModelMeshGetNodesByElementType(
-     &      elementType,
-     &      nodeTags,
-     &      nodeTags_n,
-     &      coord,
-     &      coord_n,
-     &      parametricCoord,
-     &      parametricCoord_n,
-     &      tag,
-     &      returnParametricCoord,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetNodesByElementType")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::elementType
-            type(c_ptr), intent(out)::nodeTags
-            integer(c_size_t) :: nodeTags_n
-            type(c_ptr), intent(out)::coord
-            integer(c_size_t) :: coord_n
-            type(c_ptr), intent(out)::parametricCoord
-            integer(c_size_t) :: parametricCoord_n
-            integer(c_int), value::tag
-            integer(c_int), value::returnParametricCoord
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetNodesByElementType
-
-!  Get the coordinates and the parametric coordinates (if any) of the node
-!  with tag `tag', as well as the dimension `dim' and tag `tag' of the entity
-!  on which the node is classified. This function relies on an internal cache
-!  (a vector in case of dense node numbering, a map otherwise); for large
-!  meshes accessing nodes in bulk is often preferable.
-        subroutine gmshModelMeshGetNode(
-     &      nodeTag,
-     &      coord,
-     &      coord_n,
-     &      parametricCoord,
-     &      parametricCoord_n,
-     &      dim,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetNode")
-          use, intrinsic :: iso_c_binding
-            integer(c_size_t), value::nodeTag
-            type(c_ptr), intent(out)::coord
-            integer(c_size_t) :: coord_n
-            type(c_ptr), intent(out)::parametricCoord
-            integer(c_size_t) :: parametricCoord_n
-            integer(c_int)::dim
-            integer(c_int)::tag
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetNode
-
-!  Set the coordinates and the parametric coordinates (if any) of the node
-!  with tag `tag'. This function relies on an internal cache (a vector in case
-!  of dense node numbering, a map otherwise); for large meshes accessing nodes
-!  in bulk is often preferable.
-        subroutine gmshModelMeshSetNode(
-     &      nodeTag,
-     &      coord,
-     &      coord_n,
-     &      parametricCoord,
-     &      parametricCoord_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshSetNode")
-          use, intrinsic :: iso_c_binding
-            integer(c_size_t), value::nodeTag
-            real(c_double)::coord(*)
-            integer(c_size_t), value :: coord_n
-            real(c_double)::parametricCoord(*)
-            integer(c_size_t), value :: parametricCoord_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshSetNode
-
-!  Rebuild the node cache.
-        subroutine gmshModelMeshRebuildNodeCache(
-     &      onlyIfNecessary,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshRebuildNodeCache")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::onlyIfNecessary
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshRebuildNodeCache
-
-!  Rebuild the element cache.
-        subroutine gmshModelMeshRebuildElementCache(
-     &      onlyIfNecessary,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshRebuildElementCache")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::onlyIfNecessary
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshRebuildElementCache
-
-!  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, ...].
-        subroutine gmshModelMeshGetNodesForPhysicalGroup(
-     &      dim,
-     &      tag,
-     &      nodeTags,
-     &      nodeTags_n,
-     &      coord,
-     &      coord_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetNodesForPhysicalGroup")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            type(c_ptr), intent(out)::nodeTags
-            integer(c_size_t) :: nodeTags_n
-            type(c_ptr), intent(out)::coord
-            integer(c_size_t) :: coord_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetNodesForPhysicalGroup
-
-!  Get the maximum tag `maxTag' of a node in the mesh.
-        subroutine gmshModelMeshGetMaxNodeTag(
-     &      maxTag,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetMaxNodeTag")
-          use, intrinsic :: iso_c_binding
-            integer(c_size_t)::maxTag
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetMaxNodeTag
-
-!  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.
-        subroutine gmshModelMeshAddNodes(
-     &      dim,
-     &      tag,
-     &      nodeTags,
-     &      nodeTags_n,
-     &      coord,
-     &      coord_n,
-     &      parametricCoord,
-     &      parametricCoord_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshAddNodes")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            integer(c_size_t)::nodeTags(*)
-            integer(c_size_t), value :: nodeTags_n
-            real(c_double)::coord(*)
-            integer(c_size_t), value :: coord_n
-            real(c_double)::parametricCoord(*)
-            integer(c_size_t), value :: parametricCoord_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshAddNodes
-
-!  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.
-        subroutine gmshModelMeshReclassifyNodes(
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshReclassifyNodes")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshReclassifyNodes
-
-!  Relocate the nodes classified on the entity of dimension `dim' and tag
-!  `tag' using their parametric coordinates. If `tag' < 0, relocate the nodes
-!  for all entities of dimension `dim'. If `dim' and `tag' are negative,
-!  relocate all the nodes in the mesh.
-        subroutine gmshModelMeshRelocateNodes(
-     &      dim,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshRelocateNodes")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshRelocateNodes
-
-!  Get the elements classified on the entity of dimension `dim' and tag `tag'.
-!  If `tag' < 0, get the elements for all entities of dimension `dim'. If
-!  `dim' and `tag' are negative, get all the elements in the mesh.
-!  `elementTypes' contains the MSH types of the elements (e.g. `2' for 3-node
-!  triangles: see `getElementProperties' to obtain the properties for a given
-!  element type). `elementTags' is a vector of the same length as
-!  `elementTypes'; 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 `elementTypes'; each
-!  entry is a vector of length equal to the number of elements of the given
-!  type times the number N of nodes for this type of element, that contains
-!  the node tags of all the elements of the given type, concatenated: [e1n1,
-!  e1n2, ..., e1nN, e2n1, ...].
-        subroutine gmshModelMeshGetElements(
-     &      elementTypes,
-     &      elementTypes_n,
-     &      elementTags,
-     &      elementTags_n,
-     &      elementTags_nn,
-     &      nodeTags,
-     &      nodeTags_n,
-     &      nodeTags_nn,
-     &      dim,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetElements")
-          use, intrinsic :: iso_c_binding
-            type(c_ptr), intent(out)::elementTypes
-            integer(c_size_t) :: elementTypes_n
-            type (c_ptr), intent(out)::elementTags
-            type(c_ptr), intent(out) :: elementTags_n
-            integer(c_size_t) :: elementTags_nn
-            type (c_ptr), intent(out)::nodeTags
-            type(c_ptr), intent(out) :: nodeTags_n
-            integer(c_size_t) :: nodeTags_nn
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetElements
-
-!  Get the type and node tags of the element with tag `tag', as well as the
-!  dimension `dim' and tag `tag' of the entity on which the element is
-!  classified. This function relies on an internal cache (a vector in case of
-!  dense element numbering, a map otherwise); for large meshes accessing
-!  elements in bulk is often preferable.
-        subroutine gmshModelMeshGetElement(
-     &      elementTag,
-     &      elementType,
-     &      nodeTags,
-     &      nodeTags_n,
-     &      dim,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetElement")
-          use, intrinsic :: iso_c_binding
-            integer(c_size_t), value::elementTag
-            integer(c_int)::elementType
-            type(c_ptr), intent(out)::nodeTags
-            integer(c_size_t) :: nodeTags_n
-            integer(c_int)::dim
-            integer(c_int)::tag
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetElement
-
-!  Search the mesh for an element located at coordinates (`x', `y', `z'). This
-!  function performs a search in a spatial octree. If an element is found,
-!  return its tag, type and node tags, as well as the local coordinates (`u',
-!  `v', `w') within the reference element corresponding to search location. If
-!  `dim' is >= 0, only search for elements of the given dimension. If `strict'
-!  is not set, use a tolerance to find elements near the search location.
-        subroutine gmshModelMeshGetElementByCoordinates(
-     &      x,
-     &      y,
-     &      z,
-     &      elementTag,
-     &      elementType,
-     &      nodeTags,
-     &      nodeTags_n,
-     &      u,
-     &      v,
-     &      w,
-     &      dim,
-     &      strict,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetElementByCoordinates")
-          use, intrinsic :: iso_c_binding
-            real(c_double), value::x
-            real(c_double), value::y
-            real(c_double), value::z
-            integer(c_size_t)::elementTag
-            integer(c_int)::elementType
-            type(c_ptr), intent(out)::nodeTags
-            integer(c_size_t) :: nodeTags_n
-            real(c_double)::u
-            real(c_double)::v
-            real(c_double)::w
-            integer(c_int), value::dim
-            integer(c_int), value::strict
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetElementByCoordinates
-
-!  Search the mesh for element(s) located at coordinates (`x', `y', `z'). This
-!  function performs a search in a spatial octree. Return the tags of all
-!  found elements in `elementTags'. Additional information about the elements
-!  can be accessed through `getElement' and `getLocalCoordinatesInElement'. If
-!  `dim' is >= 0, only search for elements of the given dimension. If `strict'
-!  is not set, use a tolerance to find elements near the search location.
-        subroutine gmshModelMeshGetElementsByCoordinates(
-     &      x,
-     &      y,
-     &      z,
-     &      elementTags,
-     &      elementTags_n,
-     &      dim,
-     &      strict,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetElementsByCoordinates")
-          use, intrinsic :: iso_c_binding
-            real(c_double), value::x
-            real(c_double), value::y
-            real(c_double), value::z
-            type(c_ptr), intent(out)::elementTags
-            integer(c_size_t) :: elementTags_n
-            integer(c_int), value::dim
-            integer(c_int), value::strict
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetElementsByCoordinates
-
-!  Return the local coordinates (`u', `v', `w') within the element
-!  `elementTag' corresponding to the model coordinates (`x', `y', `z'). This
-!  function relies on an internal cache (a vector in case of dense element
-!  numbering, a map otherwise); for large meshes accessing elements in bulk is
-!  often preferable.
-        subroutine gmshModelMeshGetLocalCoordinatesInElement(
-     &      elementTag,
-     &      x,
-     &      y,
-     &      z,
-     &      u,
-     &      v,
-     &      w,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetLocalCoordinatesInElement")
-          use, intrinsic :: iso_c_binding
-            integer(c_size_t), value::elementTag
-            real(c_double), value::x
-            real(c_double), value::y
-            real(c_double), value::z
-            real(c_double)::u
-            real(c_double)::v
-            real(c_double)::w
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetLocalCoordinatesInElement
-
-!  Get the types of elements in the entity of dimension `dim' and tag `tag'.
-!  If `tag' < 0, get the types for all entities of dimension `dim'. If `dim'
-!  and `tag' are negative, get all the types in the mesh.
-        subroutine gmshModelMeshGetElementTypes(
-     &      elementTypes,
-     &      elementTypes_n,
-     &      dim,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetElementTypes")
-          use, intrinsic :: iso_c_binding
-            type(c_ptr), intent(out)::elementTypes
-            integer(c_size_t) :: elementTypes_n
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetElementTypes
-
-!  Return an element type given its family name `familyName' ("Point", "Line",
-!  "Triangle", "Quadrangle", "Tetrahedron", "Pyramid", "Prism", "Hexahedron")
-!  and polynomial order `order'. If `serendip' is true, return the
-!  corresponding serendip element type (element without interior nodes).
-        function gmshModelMeshGetElementType(
-     &      familyName,
-     &      order,
-     &      serendip,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetElementType")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelMeshGetElementType
-            character(len = 1, kind = c_char)::familyName(*)
-            integer(c_int), value::order
-            integer(c_int), value::serendip
-            integer(c_int)::ierr
-          end function gmshModelMeshGetElementType
-
-!  Get the properties of an element of type `elementType': its name
-!  (`elementName'), dimension (`dim'), order (`order'), number of nodes
-!  (`numNodes'), local coordinates of the nodes in the reference element
-!  (`localNodeCoord' vector, of length `dim' times `numNodes') and number of
-!  primary (first order) nodes (`numPrimaryNodes').
-        subroutine gmshModelMeshGetElementProperties(
-     &      elementType,
-     &      elementName,
-     &      dim,
-     &      order,
-     &      numNodes,
-     &      localNodeCoord,
-     &      localNodeCoord_n,
-     &      numPrimaryNodes,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetElementProperties")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::elementType
-            type(c_ptr)::elementName(*)
-            integer(c_int)::dim
-            integer(c_int)::order
-            integer(c_int)::numNodes
-            type(c_ptr), intent(out)::localNodeCoord
-            integer(c_size_t) :: localNodeCoord_n
-            integer(c_int)::numPrimaryNodes
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetElementProperties
-
-!  Get the elements of type `elementType' classified on the entity of tag
-!  `tag'. If `tag' < 0, get the elements for all entities. `elementTags' is a
-!  vector containing 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 of the given type times the number N of nodes for
-!  this type of element, that contains the node tags of all the elements of
-!  the given type, concatenated: [e1n1, e1n2, ..., e1nN, e2n1, ...]. If
-!  `numTasks' > 1, only compute and return the part of the data indexed by
-!  `task'.
-        subroutine gmshModelMeshGetElementsByType(
-     &      elementType,
-     &      elementTags,
-     &      elementTags_n,
-     &      nodeTags,
-     &      nodeTags_n,
-     &      tag,
-     &      task,
-     &      numTasks,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetElementsByType")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::elementType
-            type(c_ptr), intent(out)::elementTags
-            integer(c_size_t) :: elementTags_n
-            type(c_ptr), intent(out)::nodeTags
-            integer(c_size_t) :: nodeTags_n
-            integer(c_int), value::tag
-            integer(c_size_t), value::task
-            integer(c_size_t), value::numTasks
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetElementsByType
-
-!  Get the maximum tag `maxTag' of an element in the mesh.
-        subroutine gmshModelMeshGetMaxElementTag(
-     &      maxTag,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetMaxElementTag")
-          use, intrinsic :: iso_c_binding
-            integer(c_size_t)::maxTag
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetMaxElementTag
-
-!  Preallocate data before calling `getElementsByType' with `numTasks' > 1.
-!  For C and C++ only.
-        subroutine gmshModelMeshPreallocateElementsByType(
-     &      elementType,
-     &      elementTag,
-     &      nodeTag,
-     &      elementTags,
-     &      elementTags_n,
-     &      nodeTags,
-     &      nodeTags_n,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshPreallocateElementsByType")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::elementType
-            integer(c_int), value::elementTag
-            integer(c_int), value::nodeTag
-            type(c_ptr), intent(out)::elementTags
-            integer(c_size_t) :: elementTags_n
-            type(c_ptr), intent(out)::nodeTags
-            integer(c_size_t) :: nodeTags_n
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshPreallocateElementsByType
-
-!  Get the quality `elementQualities' of the elements with tags `elementTags'.
-!  `qualityType' is the requested quality measure: "minSJ" for the minimal
-!  scaled jacobien, "minSICN" for the minimal signed inverted condition
-!  number, "minSIGE" for the signed inverted gradient error, "gamma" for the
-!  ratio of the inscribed to circumcribed sphere radius, "volume" for the
-!  volume. If `numTasks' > 1, only compute and return the part of the data
-!  indexed by `task'.
-        subroutine gmshModelMeshGetElementQualities(
-     &      elementTags,
-     &      elementTags_n,
-     &      elementsQuality,
-     &      elementsQuality_n,
-     &      qualityName,
-     &      task,
-     &      numTasks,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetElementQualities")
-          use, intrinsic :: iso_c_binding
-            integer(c_size_t)::elementTags(*)
-            integer(c_size_t), value :: elementTags_n
-            type(c_ptr), intent(out)::elementsQuality
-            integer(c_size_t) :: elementsQuality_n
-            character(len = 1, kind = c_char)::qualityName(*)
-            integer(c_size_t), value::task
-            integer(c_size_t), value::numTasks
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetElementQualities
-
-!  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,
-!  ...].
-        subroutine gmshModelMeshAddElements(
-     &      dim,
-     &      tag,
-     &      elementTypes,
-     &      elementTypes_n,
-     &      elementTags,
-     &      elementTags_n,
-     &      elementTags_nn,
-     &      nodeTags,
-     &      nodeTags_n,
-     &      nodeTags_nn,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshAddElements")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            integer(c_int)::elementTypes(*)
-            integer(c_size_t), value :: elementTypes_n
-            type(c_ptr), intent(out)::elementTags
-            type(c_ptr), intent(out) :: elementTags_n
-            integer(c_size_t) :: elementTags_nn
-            type(c_ptr), intent(out)::nodeTags
-            type(c_ptr), intent(out) :: nodeTags_n
-            integer(c_size_t) :: nodeTags_nn
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshAddElements
-
-!  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.
-        subroutine gmshModelMeshAddElementsByType(
-     &      tag,
-     &      elementType,
-     &      elementTags,
-     &      elementTags_n,
-     &      nodeTags,
-     &      nodeTags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshAddElementsByType")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            integer(c_int), value::elementType
-            integer(c_size_t)::elementTags(*)
-            integer(c_size_t), value :: elementTags_n
-            integer(c_size_t)::nodeTags(*)
-            integer(c_size_t), value :: nodeTags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshAddElementsByType
-
-!  Get the numerical quadrature information for the given element type
-!  `elementType' and integration rule `integrationType', where
-!  `integrationType' concatenates the integration rule family name with the
-!  desired order (e.g. "Gauss4" for a quadrature suited for integrating 4th
-!  order polynomials). The "CompositeGauss" family uses tensor-product rules
-!  based the 1D Gauss-Legendre rule; the "Gauss" family uses an economic
-!  scheme when available (i.e. with a minimal number of points), and falls
-!  back to "CompositeGauss" otherwise. Note that integration points for the
-!  "Gauss" family can fall outside of the reference element for high-order
-!  rules. `localCoord' contains the u, v, w coordinates of the G integration
-!  points in the reference element: [g1u, g1v, g1w, ..., gGu, gGv, gGw].
-!  `weights' contains the associated weights: [g1q, ..., gGq].
-        subroutine gmshModelMeshGetIntegrationPoints(
-     &      elementType,
-     &      integrationType,
-     &      localCoord,
-     &      localCoord_n,
-     &      weights,
-     &      weights_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetIntegrationPoints")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::elementType
-            character(len = 1, kind = c_char)::integrationType(*)
-            type(c_ptr), intent(out)::localCoord
-            integer(c_size_t) :: localCoord_n
-            type(c_ptr), intent(out)::weights
-            integer(c_size_t) :: weights_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetIntegrationPoints
-
-!  Get the Jacobians of all the elements of type `elementType' classified on
-!  the entity of tag `tag', at the G evaluation points `localCoord' given as
-!  concatenated triplets of coordinates in the reference element [g1u, g1v,
-!  g1w, ..., gGu, gGv, gGw]. Data is returned by element, with elements in the
-!  same order as in `getElements' and `getElementsByType'. `jacobians'
-!  contains for each element the 9 entries of the 3x3 Jacobian matrix at each
-!  evaluation point. The matrix is returned by column: [e1g1Jxu, e1g1Jyu,
-!  e1g1Jzu, e1g1Jxv, ..., e1g1Jzw, e1g2Jxu, ..., e1gGJzw, e2g1Jxu, ...], with
-!  Jxu=dx/du, Jyu=dy/du, etc. `determinants' contains for each element the
-!  determinant of the Jacobian matrix at each evaluation point: [e1g1, e1g2,
-!  ... e1gG, e2g1, ...]. `coord' contains for each element the x, y, z
-!  coordinates of the evaluation points. If `tag' < 0, get the Jacobian data
-!  for all entities. If `numTasks' > 1, only compute and return the part of
-!  the data indexed by `task'.
-        subroutine gmshModelMeshGetJacobians(
-     &      elementType,
-     &      localCoord,
-     &      localCoord_n,
-     &      jacobians,
-     &      jacobians_n,
-     &      determinants,
-     &      determinants_n,
-     &      coord,
-     &      coord_n,
-     &      tag,
-     &      task,
-     &      numTasks,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetJacobians")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::elementType
-            real(c_double)::localCoord(*)
-            integer(c_size_t), value :: localCoord_n
-            type(c_ptr), intent(out)::jacobians
-            integer(c_size_t) :: jacobians_n
-            type(c_ptr), intent(out)::determinants
-            integer(c_size_t) :: determinants_n
-            type(c_ptr), intent(out)::coord
-            integer(c_size_t) :: coord_n
-            integer(c_int), value::tag
-            integer(c_size_t), value::task
-            integer(c_size_t), value::numTasks
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetJacobians
-
-!  Preallocate data before calling `getJacobians' with `numTasks' > 1. For C
-!  and C++ only.
-        subroutine gmshModelMeshPreallocateJacobians(
-     &      elementType,
-     &      numEvaluationPoints,
-     &      allocateJacobians,
-     &      allocateDeterminants,
-     &      allocateCoord,
-     &      jacobians,
-     &      jacobians_n,
-     &      determinants,
-     &      determinants_n,
-     &      coord,
-     &      coord_n,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshPreallocateJacobians")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::elementType
-            integer(c_int), value::numEvaluationPoints
-            integer(c_int), value::allocateJacobians
-            integer(c_int), value::allocateDeterminants
-            integer(c_int), value::allocateCoord
-            type(c_ptr), intent(out)::jacobians
-            integer(c_size_t) :: jacobians_n
-            type(c_ptr), intent(out)::determinants
-            integer(c_size_t) :: determinants_n
-            type(c_ptr), intent(out)::coord
-            integer(c_size_t) :: coord_n
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshPreallocateJacobians
-
-!  Get the Jacobian for a single element `elementTag', at the G evaluation
-!  points `localCoord' given as concatenated triplets of coordinates in the
-!  reference element [g1u, g1v, g1w, ..., gGu, gGv, gGw]. `jacobians' contains
-!  the 9 entries of the 3x3 Jacobian matrix at each evaluation point. The
-!  matrix is returned by column: [e1g1Jxu, e1g1Jyu, e1g1Jzu, e1g1Jxv, ...,
-!  e1g1Jzw, e1g2Jxu, ..., e1gGJzw, e2g1Jxu, ...], with Jxu=dx/du, Jyu=dy/du,
-!  etc. `determinants' contains the determinant of the Jacobian matrix at each
-!  evaluation point. `coord' contains the x, y, z coordinates of the
-!  evaluation points. This function relies on an internal cache (a vector in
-!  case of dense element numbering, a map otherwise); for large meshes
-!  accessing Jacobians in bulk is often preferable.
-        subroutine gmshModelMeshGetJacobian(
-     &      elementTag,
-     &      localCoord,
-     &      localCoord_n,
-     &      jacobians,
-     &      jacobians_n,
-     &      determinants,
-     &      determinants_n,
-     &      coord,
-     &      coord_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetJacobian")
-          use, intrinsic :: iso_c_binding
-            integer(c_size_t), value::elementTag
-            real(c_double)::localCoord(*)
-            integer(c_size_t), value :: localCoord_n
-            type(c_ptr), intent(out)::jacobians
-            integer(c_size_t) :: jacobians_n
-            type(c_ptr), intent(out)::determinants
-            integer(c_size_t) :: determinants_n
-            type(c_ptr), intent(out)::coord
-            integer(c_size_t) :: coord_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetJacobian
-
-!  Get the basis functions of the element of type `elementType' at the
-!  evaluation points `localCoord' (given as concatenated triplets of
-!  coordinates in the reference element [g1u, g1v, g1w, ..., gGu, gGv, gGw]),
-!  for the function space `functionSpaceType'. Currently supported function
-!  spaces include "Lagrange" and "GradLagrange" for isoparametric Lagrange
-!  basis functions and their gradient in the u, v, w coordinates of the
-!  reference element; "LagrangeN" and "GradLagrangeN", with N = 1, 2, ..., for
-!  N-th order Lagrange basis functions; "H1LegendreN" and "GradH1LegendreN",
-!  with N = 1, 2, ..., for N-th order hierarchical H1 Legendre functions;
-!  "HcurlLegendreN" and "CurlHcurlLegendreN", with N = 1, 2, ..., for N-th
-!  order curl-conforming basis functions. `numComponents' returns the number C
-!  of components of a basis function (e.g. 1 for scalar functions and 3 for
-!  vector functions). `basisFunctions' returns the value of the N basis
-!  functions at the evaluation points, i.e. [g1f1, g1f2, ..., g1fN, g2f1, ...]
-!  when C == 1 or [g1f1u, g1f1v, g1f1w, g1f2u, ..., g1fNw, g2f1u, ...] when C
-!  == 3. For basis functions that depend on the orientation of the elements,
-!  all values for the first orientation are returned first, followed by values
-!  for the second, etc. `numOrientations' returns the overall number of
-!  orientations. If `wantedOrientations' is not empty, only return the values
-!  for the desired orientation indices.
-        subroutine gmshModelMeshGetBasisFunctions(
-     &      elementType,
-     &      localCoord,
-     &      localCoord_n,
-     &      functionSpaceType,
-     &      numComponents,
-     &      basisFunctions,
-     &      basisFunctions_n,
-     &      numOrientations,
-     &      wantedOrientations,
-     &      wantedOrientations_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetBasisFunctions")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::elementType
-            real(c_double)::localCoord(*)
-            integer(c_size_t), value :: localCoord_n
-            character(len = 1, kind = c_char)::functionSpaceType(*)
-            integer(c_int)::numComponents
-            type(c_ptr), intent(out)::basisFunctions
-            integer(c_size_t) :: basisFunctions_n
-            integer(c_int)::numOrientations
-            integer(c_int)::wantedOrientations(*)
-            integer(c_size_t), value :: wantedOrientations_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetBasisFunctions
-
-!  Get the orientation index of the elements of type `elementType' in the
-!  entity of tag `tag'. The arguments have the same meaning as in
-!  `getBasisFunctions'. `basisFunctionsOrientation' is a vector giving for
-!  each element the orientation index in the values returned by
-!  `getBasisFunctions'. For Lagrange basis functions the call is superfluous
-!  as it will return a vector of zeros.
-        subroutine gmshModelMeshGetBasisFunctionsOrientation(
-     &      elementType,
-     &      functionSpaceType,
-     &      basisFunctionsOrientation,
-     &      basisFunctionsOrientation_n,
-     &      tag,
-     &      task,
-     &      numTasks,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetBasisFunctionsOrientation")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::elementType
-            character(len = 1, kind = c_char)::functionSpaceType(*)
-            type(c_ptr), intent(out)::basisFunctionsOrientation
-            integer(c_size_t) :: basisFunctionsOrientation_n
-            integer(c_int), value::tag
-            integer(c_size_t), value::task
-            integer(c_size_t), value::numTasks
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetBasisFunctionsOrientation
-
-!  Get the orientation of a single element `elementTag'.
-
-!  Get the number of possible orientations for elements of type `elementType'
-!  and function space named `functionSpaceType'.
-        function gmshModelMeshGetNumberOfOrientations(
-     &      elementType,
-     &      functionSpaceType,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetNumberOfOrientations")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelMeshGetNumberOfOrientations
-            integer(c_int), value::elementType
-            character(len = 1, kind = c_char)::functionSpaceType(*)
-            integer(c_int)::ierr
-          end function gmshModelMeshGetNumberOfOrientations
-
-!  Preallocate data before calling `getBasisFunctionsOrientation' with
-!  `numTasks' > 1. For C and C++ only.
-
-!  Get the global unique mesh edge identifiers `edgeTags' and orientations
-!  `edgeOrientation' for an input list of node tag pairs defining these edges,
-!  concatenated in the vector `nodeTags'. Mesh edges are created e.g. by
-!  `createEdges()', `getKeys()' or `addEdges()'. The reference positive
-!  orientation is n1 < n2, where n1 and n2 are the tags of the two edge nodes,
-!  which corresponds to the local orientation of edge-based basis functions as
-!  well.
-        subroutine gmshModelMeshGetEdges(
-     &      nodeTags,
-     &      nodeTags_n,
-     &      edgeTags,
-     &      edgeTags_n,
-     &      edgeOrientations,
-     &      edgeOrientations_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetEdges")
-          use, intrinsic :: iso_c_binding
-            integer(c_size_t)::nodeTags(*)
-            integer(c_size_t), value :: nodeTags_n
-            type(c_ptr), intent(out)::edgeTags
-            integer(c_size_t) :: edgeTags_n
-            type(c_ptr), intent(out)::edgeOrientations
-            integer(c_size_t) :: edgeOrientations_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetEdges
-
-!  Get the global unique mesh face identifiers `faceTags' and orientations
-!  `faceOrientations' for an input list of node tag triplets (if `faceType' ==
-!  3) or quadruplets (if `faceType' == 4) defining these faces, concatenated
-!  in the vector `nodeTags'. Mesh faces are created e.g. by `createFaces()',
-!  `getKeys()' or `addFaces()'.
-        subroutine gmshModelMeshGetFaces(
-     &      faceType,
-     &      nodeTags,
-     &      nodeTags_n,
-     &      faceTags,
-     &      faceTags_n,
-     &      faceOrientations,
-     &      faceOrientations_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetFaces")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::faceType
-            integer(c_size_t)::nodeTags(*)
-            integer(c_size_t), value :: nodeTags_n
-            type(c_ptr), intent(out)::faceTags
-            integer(c_size_t) :: faceTags_n
-            type(c_ptr), intent(out)::faceOrientations
-            integer(c_size_t) :: faceOrientations_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetFaces
-
-!  Create unique mesh edges for the entities `dimTags'.
-        subroutine gmshModelMeshCreateEdges(
-     &      dimTags,
-     &      dimTags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshCreateEdges")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshCreateEdges
-
-!  Create unique mesh faces for the entities `dimTags'.
-        subroutine gmshModelMeshCreateFaces(
-     &      dimTags,
-     &      dimTags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshCreateFaces")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshCreateFaces
-
-!  Get the global unique identifiers `edgeTags' and the nodes `edgeNodes' of
-!  the edges in the mesh. Mesh edges are created e.g. by `createEdges()',
-!  `getKeys()' or addEdges().
-        subroutine gmshModelMeshGetAllEdges(
-     &      edgeTags,
-     &      edgeTags_n,
-     &      edgeNodes,
-     &      edgeNodes_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetAllEdges")
-          use, intrinsic :: iso_c_binding
-            type(c_ptr), intent(out)::edgeTags
-            integer(c_size_t) :: edgeTags_n
-            type(c_ptr), intent(out)::edgeNodes
-            integer(c_size_t) :: edgeNodes_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetAllEdges
-
-!  Get the global unique identifiers `faceTags' and the nodes `faceNodes' of
-!  the faces of type `faceType' in the mesh. Mesh faces are created e.g. by
-!  `createFaces()', `getKeys()' or addFaces().
-        subroutine gmshModelMeshGetAllFaces(
-     &      faceType,
-     &      faceTags,
-     &      faceTags_n,
-     &      faceNodes,
-     &      faceNodes_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetAllFaces")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::faceType
-            type(c_ptr), intent(out)::faceTags
-            integer(c_size_t) :: faceTags_n
-            type(c_ptr), intent(out)::faceNodes
-            integer(c_size_t) :: faceNodes_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetAllFaces
-
-!  Add mesh edges defined by their global unique identifiers `edgeTags' and
-!  their nodes `edgeNodes'.
-        subroutine gmshModelMeshAddEdges(
-     &      edgeTags,
-     &      edgeTags_n,
-     &      edgeNodes,
-     &      edgeNodes_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshAddEdges")
-          use, intrinsic :: iso_c_binding
-            integer(c_size_t)::edgeTags(*)
-            integer(c_size_t), value :: edgeTags_n
-            integer(c_size_t)::edgeNodes(*)
-            integer(c_size_t), value :: edgeNodes_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshAddEdges
-
-!  Add mesh faces of type `faceType' defined by their global unique
-!  identifiers `faceTags' and their nodes `faceNodes'.
-        subroutine gmshModelMeshAddFaces(
-     &      faceType,
-     &      faceTags,
-     &      faceTags_n,
-     &      faceNodes,
-     &      faceNodes_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshAddFaces")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::faceType
-            integer(c_size_t)::faceTags(*)
-            integer(c_size_t), value :: faceTags_n
-            integer(c_size_t)::faceNodes(*)
-            integer(c_size_t), value :: faceNodes_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshAddFaces
-
-!  Generate the pair of keys for the elements of type `elementType' in the
-!  entity of tag `tag', for the `functionSpaceType' function space. Each pair
-!  (`typeKey', `entityKey') uniquely identifies a basis function in the
-!  function space. If `returnCoord' is set, the `coord' vector contains the x,
-!  y, z coordinates locating basis functions for sorting purposes. Warning:
-!  this is an experimental feature and will probably change in a future
-!  release.
-        subroutine gmshModelMeshGetKeys(
-     &      elementType,
-     &      functionSpaceType,
-     &      typeKeys,
-     &      typeKeys_n,
-     &      entityKeys,
-     &      entityKeys_n,
-     &      coord,
-     &      coord_n,
-     &      tag,
-     &      returnCoord,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetKeys")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::elementType
-            character(len = 1, kind = c_char)::functionSpaceType(*)
-            type(c_ptr), intent(out)::typeKeys
-            integer(c_size_t) :: typeKeys_n
-            type(c_ptr), intent(out)::entityKeys
-            integer(c_size_t) :: entityKeys_n
-            type(c_ptr), intent(out)::coord
-            integer(c_size_t) :: coord_n
-            integer(c_int), value::tag
-            integer(c_int), value::returnCoord
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetKeys
-
-!  Get the pair of keys for a single element `elementTag'.
-        subroutine gmshModelMeshGetKeysForElement(
-     &      elementTag,
-     &      functionSpaceType,
-     &      typeKeys,
-     &      typeKeys_n,
-     &      entityKeys,
-     &      entityKeys_n,
-     &      coord,
-     &      coord_n,
-     &      returnCoord,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetKeysForElement")
-          use, intrinsic :: iso_c_binding
-            integer(c_size_t), value::elementTag
-            character(len = 1, kind = c_char)::functionSpaceType(*)
-            type(c_ptr), intent(out)::typeKeys
-            integer(c_size_t) :: typeKeys_n
-            type(c_ptr), intent(out)::entityKeys
-            integer(c_size_t) :: entityKeys_n
-            type(c_ptr), intent(out)::coord
-            integer(c_size_t) :: coord_n
-            integer(c_int), value::returnCoord
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetKeysForElement
-
-!  Get the number of keys by elements of type `elementType' for function space
-!  named `functionSpaceType'.
-        function gmshModelMeshGetNumberOfKeys(
-     &      elementType,
-     &      functionSpaceType,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetNumberOfKeys")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelMeshGetNumberOfKeys
-            integer(c_int), value::elementType
-            character(len = 1, kind = c_char)::functionSpaceType(*)
-            integer(c_int)::ierr
-          end function gmshModelMeshGetNumberOfKeys
-
-!  Get information about the pair of `keys'. `infoKeys' returns information
-!  about the functions associated with the pairs (`typeKeys', `entityKey').
-!  `infoKeys[0].first' describes the type of function (0 for  vertex function,
-!  1 for edge function, 2 for face function and 3 for bubble function).
-!  `infoKeys[0].second' gives the order of the function associated with the
-!  key. Warning: this is an experimental feature and will probably change in a
-!  future release.
-        subroutine gmshModelMeshGetKeysInformation(
-     &      typeKeys,
-     &      typeKeys_n,
-     &      entityKeys,
-     &      entityKeys_n,
-     &      elementType,
-     &      functionSpaceType,
-     &      infoKeys,
-     &      infoKeys_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetKeysInformation")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::typeKeys(*)
-            integer(c_size_t), value :: typeKeys_n
-            integer(c_size_t)::entityKeys(*)
-            integer(c_size_t), value :: entityKeys_n
-            integer(c_int), value::elementType
-            character(len = 1, kind = c_char)::functionSpaceType(*)
-            type(c_ptr), intent(out)::infoKeys
-            integer(c_size_t) :: infoKeys_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetKeysInformation
-
-!  Get the barycenters of all elements of type `elementType' classified on the
-!  entity of tag `tag'. If `primary' is set, only the primary nodes of the
-!  elements are taken into account for the barycenter calculation. If `fast'
-!  is set, the function returns the sum of the primary node coordinates
-!  (without normalizing by the number of nodes). If `tag' < 0, get the
-!  barycenters for all entities. If `numTasks' > 1, only compute and return
-!  the part of the data indexed by `task'.
-        subroutine gmshModelMeshGetBarycenters(
-     &      elementType,
-     &      tag,
-     &      fast,
-     &      primary,
-     &      barycenters,
-     &      barycenters_n,
-     &      task,
-     &      numTasks,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetBarycenters")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::elementType
-            integer(c_int), value::tag
-            integer(c_int), value::fast
-            integer(c_int), value::primary
-            type(c_ptr), intent(out)::barycenters
-            integer(c_size_t) :: barycenters_n
-            integer(c_size_t), value::task
-            integer(c_size_t), value::numTasks
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetBarycenters
-
-!  Preallocate data before calling `getBarycenters' with `numTasks' > 1. For C
-!  and C++ only.
-        subroutine gmshModelMeshPreallocateBarycenters(
-     &      elementType,
-     &      barycenters,
-     &      barycenters_n,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshPreallocateBarycenters")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::elementType
-            type(c_ptr), intent(out)::barycenters
-            integer(c_size_t) :: barycenters_n
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshPreallocateBarycenters
-
-!  Get the nodes on the edges of all elements of type `elementType' classified
-!  on the entity of tag `tag'. `nodeTags' contains the node tags of the edges
-!  for all the elements: [e1a1n1, e1a1n2, e1a2n1, ...]. Data is returned by
-!  element, with elements in the same order as in `getElements' and
-!  `getElementsByType'. If `primary' is set, only the primary (begin/end)
-!  nodes of the edges are returned. If `tag' < 0, get the edge nodes for all
-!  entities. If `numTasks' > 1, only compute and return the part of the data
-!  indexed by `task'.
-        subroutine gmshModelMeshGetElementEdgeNodes(
-     &      elementType,
-     &      nodeTags,
-     &      nodeTags_n,
-     &      tag,
-     &      primary,
-     &      task,
-     &      numTasks,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetElementEdgeNodes")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::elementType
-            type(c_ptr), intent(out)::nodeTags
-            integer(c_size_t) :: nodeTags_n
-            integer(c_int), value::tag
-            integer(c_int), value::primary
-            integer(c_size_t), value::task
-            integer(c_size_t), value::numTasks
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetElementEdgeNodes
-
-!  Get the nodes on the faces of type `faceType' (3 for triangular faces, 4
-!  for quadrangular faces) of all elements of type `elementType' classified on
-!  the entity of tag `tag'. `nodeTags' contains the node tags of the faces for
-!  all elements: [e1f1n1, ..., e1f1nFaceType, e1f2n1, ...]. Data is returned
-!  by element, with elements in the same order as in `getElements' and
-!  `getElementsByType'. If `primary' is set, only the primary (corner) nodes
-!  of the faces are returned. If `tag' < 0, get the face nodes for all
-!  entities. If `numTasks' > 1, only compute and return the part of the data
-!  indexed by `task'.
-        subroutine gmshModelMeshGetElementFaceNodes(
-     &      elementType,
-     &      faceType,
-     &      nodeTags,
-     &      nodeTags_n,
-     &      tag,
-     &      primary,
-     &      task,
-     &      numTasks,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetElementFaceNodes")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::elementType
-            integer(c_int), value::faceType
-            type(c_ptr), intent(out)::nodeTags
-            integer(c_size_t) :: nodeTags_n
-            integer(c_int), value::tag
-            integer(c_int), value::primary
-            integer(c_size_t), value::task
-            integer(c_size_t), value::numTasks
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetElementFaceNodes
-
-!  Get the ghost elements `elementTags' and their associated `partitions'
-!  stored in the ghost entity of dimension `dim' and tag `tag'.
-        subroutine gmshModelMeshGetGhostElements(
-     &      dim,
-     &      tag,
-     &      elementTags,
-     &      elementTags_n,
-     &      partitions,
-     &      partitions_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetGhostElements")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            type(c_ptr), intent(out)::elementTags
-            integer(c_size_t) :: elementTags_n
-            type(c_ptr), intent(out)::partitions
-            integer(c_size_t) :: partitions_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetGhostElements
-
-!  Set a mesh size constraint on the model entities `dimTags'. Currently only
-!  entities of dimension 0 (points) are handled.
-        subroutine gmshModelMeshSetSize(
-     &      dimTags,
-     &      dimTags_n,
-     &      size,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshSetSize")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            real(c_double), value::size
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshSetSize
-
-!  Get the mesh size constraints (if any) associated with the model entities
-!  `dimTags'. A zero entry in the output `sizes' vector indicates that no size
-!  constraint is specified on the corresponding entity.
-        subroutine gmshModelMeshGetSizes(
-     &      dimTags,
-     &      dimTags_n,
-     &      sizes,
-     &      sizes_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetSizes")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            type(c_ptr), intent(out)::sizes
-            integer(c_size_t) :: sizes_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetSizes
-
-!  Set mesh size constraints at the given parametric points `parametricCoord'
-!  on the model entity of dimension `dim' and tag `tag'. Currently only
-!  entities of dimension 1 (lines) are handled.
-        subroutine gmshModelMeshSetSizeAtParametricPoints(
-     &      dim,
-     &      tag,
-     &      parametricCoord,
-     &      parametricCoord_n,
-     &      sizes,
-     &      sizes_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshSetSizeAtParametricPoints")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            real(c_double)::parametricCoord(*)
-            integer(c_size_t), value :: parametricCoord_n
-            real(c_double)::sizes(*)
-            integer(c_size_t), value :: sizes_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshSetSizeAtParametricPoints
-
-!  Set a mesh size callback for the current model. The callback function
-!  should take six arguments as input (`dim', `tag', `x', `y', `z' and `lc').
-!  The first two integer arguments correspond to the dimension `dim' and tag
-!  `tag' of the entity being meshed. The next four double precision arguments
-!  correspond to the coordinates `x', `y' and `z' around which to prescribe
-!  the mesh size and to the mesh size `lc' that would be prescribed if the
-!  callback had not been called. The callback function should return a double
-!  precision number specifying the desired mesh size; returning `lc' is
-!  equivalent to a no-op.
-        subroutine gmshModelMeshSetSizeCallback(
-     &      callback,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshSetSizeCallback")
-          use, intrinsic :: iso_c_binding
-            type (C_FUNPTR)::callback ! to do 
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshSetSizeCallback
-
-!  Remove the mesh size callback from the current model.
-        subroutine gmshModelMeshRemoveSizeCallback(
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshRemoveSizeCallback")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshRemoveSizeCallback
-
-!  Set a transfinite meshing constraint on the curve `tag', with `numNodes'
-!  nodes distributed according to `meshType' and `coef'. Currently supported
-!  types are "Progression" (geometrical progression with power `coef'), "Bump"
-!  (refinement toward both extremities of the curve) and "Beta" (beta law).
-        subroutine gmshModelMeshSetTransfiniteCurve(
-     &      tag,
-     &      numNodes,
-     &      meshType,
-     &      coef,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshSetTransfiniteCurve")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            integer(c_int), value::numNodes
-            character(len = 1, kind = c_char)::meshType(*)
-            real(c_double), value::coef
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshSetTransfiniteCurve
-
-!  Set 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.
-        subroutine gmshModelMeshSetTransfiniteSurface(
-     &      tag,
-     &      arrangement,
-     &      cornerTags,
-     &      cornerTags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshSetTransfiniteSurface")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            character(len = 1, kind = c_char)::arrangement(*)
-            integer(c_int)::cornerTags(*)
-            integer(c_size_t), value :: cornerTags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshSetTransfiniteSurface
-
-!  Set a transfinite meshing constraint on the surface `tag'. `cornerTags' can
-!  be used to specify the (6 or 8) corners of the transfinite interpolation
-!  explicitly.
-        subroutine gmshModelMeshSetTransfiniteVolume(
-     &      tag,
-     &      cornerTags,
-     &      cornerTags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshSetTransfiniteVolume")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            integer(c_int)::cornerTags(*)
-            integer(c_size_t), value :: cornerTags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshSetTransfiniteVolume
-
-!  Set transfinite meshing constraints on the model entities in `dimTag'.
-!  Transfinite meshing constraints are added to the curves of the quadrangular
-!  surfaces and to the faces of 6-sided volumes. Quadragular faces with a
-!  corner angle superior to `cornerAngle' (in radians) are ignored. The number
-!  of points is automatically determined from the sizing constraints. If
-!  `dimTag' is empty, the constraints are applied to all entities in the
-!  model. If `recombine' is true, the recombine flag is automatically set on
-!  the transfinite surfaces.
-        subroutine gmshModelMeshSetTransfiniteAutomatic(
-     &      dimTags,
-     &      dimTags_n,
-     &      cornerAngle,
-     &      recombine,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshSetTransfiniteAutomatic")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            real(c_double), value::cornerAngle
-            integer(c_int), value::recombine
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshSetTransfiniteAutomatic
-
-!  Set a recombination meshing constraint on the model entity of dimension
-!  `dim' and tag `tag'. Currently only entities of dimension 2 (to recombine
-!  triangles into quadrangles) are supported; `angle' specifies the threshold
-!  angle for the simple recombination algorithm..
-        subroutine gmshModelMeshSetRecombine(
-     &      dim,
-     &      tag,
-     &      angle,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshSetRecombine")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            real(c_double), value::angle
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshSetRecombine
-
-!  Set a smoothing meshing constraint on the model entity of dimension `dim'
-!  and tag `tag'. `val' iterations of a Laplace smoother are applied.
-        subroutine gmshModelMeshSetSmoothing(
-     &      dim,
-     &      tag,
-     &      val,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshSetSmoothing")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            integer(c_int), value::val
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshSetSmoothing
-
-!  Set a reverse meshing constraint on the model 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 geometry). If `val' is false, the mesh is left
-!  as-is.
-        subroutine gmshModelMeshSetReverse(
-     &      dim,
-     &      tag,
-     &      val,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshSetReverse")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            integer(c_int), value::val
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshSetReverse
-
-!  Set the meshing algorithm on the model entity of dimension `dim' and tag
-!  `tag'. Currently only supported for `dim' == 2.
-        subroutine gmshModelMeshSetAlgorithm(
-     &      dim,
-     &      tag,
-     &      val,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshSetAlgorithm")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            integer(c_int), value::val
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshSetAlgorithm
-
-!  Force the mesh size to be extended from the boundary, or not, for the model
-!  entity of dimension `dim' and tag `tag'. Currently only supported for `dim'
-!  == 2.
-        subroutine gmshModelMeshSetSizeFromBoundary(
-     &      dim,
-     &      tag,
-     &      val,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshSetSizeFromBoundary")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            integer(c_int), value::val
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshSetSizeFromBoundary
-
-!  Set a compound meshing constraint on the model entities of dimension `dim'
-!  and tags `tags'. During meshing, compound entities are treated as a single
-!  discrete entity, which is automatically reparametrized.
-        subroutine gmshModelMeshSetCompound(
-     &      dim,
-     &      tags,
-     &      tags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshSetCompound")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int)::tags(*)
-            integer(c_size_t), value :: tags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshSetCompound
-
-!  Set meshing constraints on the bounding surfaces of the volume of tag `tag'
-!  so that all surfaces are oriented with outward pointing normals; and if a
-!  mesh already exists, reorient it. Currently only available with the
-!  OpenCASCADE kernel, as it relies on the STL triangulation.
-        subroutine gmshModelMeshSetOutwardOrientation(
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshSetOutwardOrientation")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshSetOutwardOrientation
-
-!  Remove all meshing constraints from the model entities `dimTags'. If
-!  `dimTags' is empty, remove all constraings.
-        subroutine gmshModelMeshRemoveConstraints(
-     &      dimTags,
-     &      dimTags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshRemoveConstraints")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshRemoveConstraints
-
-!  Embed the model entities of dimension `dim' and tags `tags' in the
-!  (`inDim', `inTag') model entity. The dimension `dim' can 0, 1 or 2 and must
-!  be strictly smaller than `inDim', which must be either 2 or 3. The embedded
-!  entities should not intersect each other or be part of the boundary of the
-!  entity `inTag', whose mesh will conform to the mesh of the embedded
-!  entities. With the OpenCASCADE kernel, if the `fragment' operation is
-!  applied to entities of different dimensions, the lower dimensional entities
-!  will be automatically embedded in the higher dimensional entities if they
-!  are not on their boundary.
-        subroutine gmshModelMeshEmbed(
-     &      dim,
-     &      tags,
-     &      tags_n,
-     &      inDim,
-     &      inTag,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshEmbed")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int)::tags(*)
-            integer(c_size_t), value :: tags_n
-            integer(c_int), value::inDim
-            integer(c_int), value::inTag
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshEmbed
-
-!  Remove embedded entities from the model entities `dimTags'. if `dim' is >=
-!  0, only remove embedded entities of the given dimension (e.g. embedded
-!  points if `dim' == 0).
-        subroutine gmshModelMeshRemoveEmbedded(
-     &      dimTags,
-     &      dimTags_n,
-     &      dim,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshRemoveEmbedded")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            integer(c_int), value::dim
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshRemoveEmbedded
-
-!  Get the entities (if any) embedded in the model entity of dimension `dim'
-!  and tag `tag'.
-        subroutine gmshModelMeshGetEmbedded(
-     &      dim,
-     &      tag,
-     &      dimTags,
-     &      dimTags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetEmbedded")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            type(c_ptr), intent(out)::dimTags
-            integer(c_size_t) :: dimTags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetEmbedded
-
-!  Reorder the elements of type `elementType' classified on the entity of tag
-!  `tag' according to `ordering'.
-        subroutine gmshModelMeshReorderElements(
-     &      elementType,
-     &      tag,
-     &      ordering,
-     &      ordering_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshReorderElements")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::elementType
-            integer(c_int), value::tag
-            integer(c_size_t)::ordering(*)
-            integer(c_size_t), value :: ordering_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshReorderElements
-
-!  Renumber the node tags in a continuous sequence.
-        subroutine gmshModelMeshRenumberNodes(
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshRenumberNodes")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshRenumberNodes
-
-!  Renumber the element tags in a continuous sequence.
-        subroutine gmshModelMeshRenumberElements(
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshRenumberElements")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshRenumberElements
-
-!  Set the meshes of the entities of dimension `dim' and tag `tags' as
-!  periodic copies of the meshes of entities `tagsMaster', using the affine
-!  transformation specified in `affineTransformation' (16 entries of a 4x4
-!  matrix, by row). If used after meshing, generate the periodic node
-!  correspondence information assuming the meshes of entities `tags'
-!  effectively match the meshes of entities `tagsMaster' (useful for
-!  structured and extruded meshes). Currently only available for @code{dim} ==
-!  1 and @code{dim} == 2.
-        subroutine gmshModelMeshSetPeriodic(
-     &      dim,
-     &      tags,
-     &      tags_n,
-     &      tagsMaster,
-     &      tagsMaster_n,
-     &      affineTransform,
-     &      affineTransform_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshSetPeriodic")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int)::tags(*)
-            integer(c_size_t), value :: tags_n
-            integer(c_int)::tagsMaster(*)
-            integer(c_size_t), value :: tagsMaster_n
-            real(c_double)::affineTransform(*)
-            integer(c_size_t), value :: affineTransform_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshSetPeriodic
-
-!  Get master entities `tagsMaster' for the entities of dimension `dim' and
-!  tags `tags'.
-        subroutine gmshModelMeshGetPeriodic(
-     &      dim,
-     &      tags,
-     &      tags_n,
-     &      tagMaster,
-     &      tagMaster_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetPeriodic")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int)::tags(*)
-            integer(c_size_t), value :: tags_n
-            type(c_ptr), intent(out)::tagMaster
-            integer(c_size_t) :: tagMaster_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetPeriodic
-
-!  Get the master entity `tagMaster', the node tags `nodeTags' and their
-!  corresponding master node tags `nodeTagsMaster', and the affine transform
-!  `affineTransform' for the entity of dimension `dim' and tag `tag'. If
-!  `includeHighOrderNodes' is set, include high-order nodes in the returned
-!  data.
-        subroutine gmshModelMeshGetPeriodicNodes(
-     &      dim,
-     &      tag,
-     &      tagMaster,
-     &      nodeTags,
-     &      nodeTags_n,
-     &      nodeTagsMaster,
-     &      nodeTagsMaster_n,
-     &      affineTransform,
-     &      affineTransform_n,
-     &      includeHighOrderNodes,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetPeriodicNodes")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            integer(c_int)::tagMaster
-            type(c_ptr), intent(out)::nodeTags
-            integer(c_size_t) :: nodeTags_n
-            type(c_ptr), intent(out)::nodeTagsMaster
-            integer(c_size_t) :: nodeTagsMaster_n
-            type(c_ptr), intent(out)::affineTransform
-            integer(c_size_t) :: affineTransform_n
-            integer(c_int), value::includeHighOrderNodes
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetPeriodicNodes
-
-!  Get the master entity `tagMaster' and the key pairs (`typeKeyMaster',
-!  `entityKeyMaster') corresponding to the entity `tag' and the key pairs
-!  (`typeKey', `entityKey') for the elements of type `elementType' and
-!  function space type `functionSpaceType'. If `returnCoord' is set, the
-!  `coord' and `coordMaster' vectors contain the x, y, z coordinates locating
-!  basis functions for sorting purposes.
-        subroutine gmshModelMeshGetPeriodicKeys(
-     &      elementType,
-     &      functionSpaceType,
-     &      tag,
-     &      tagMaster,
-     &      typeKeys,
-     &      typeKeys_n,
-     &      typeKeysMaster,
-     &      typeKeysMaster_n,
-     &      entityKeys,
-     &      entityKeys_n,
-     &      entityKeysMaster,
-     &      entityKeysMaster_n,
-     &      coord,
-     &      coord_n,
-     &      coordMaster,
-     &      coordMaster_n,
-     &      returnCoord,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetPeriodicKeys")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::elementType
-            character(len = 1, kind = c_char)::functionSpaceType(*)
-            integer(c_int), value::tag
-            integer(c_int)::tagMaster
-            type(c_ptr), intent(out)::typeKeys
-            integer(c_size_t) :: typeKeys_n
-            type(c_ptr), intent(out)::typeKeysMaster
-            integer(c_size_t) :: typeKeysMaster_n
-            type(c_ptr), intent(out)::entityKeys
-            integer(c_size_t) :: entityKeys_n
-            type(c_ptr), intent(out)::entityKeysMaster
-            integer(c_size_t) :: entityKeysMaster_n
-            type(c_ptr), intent(out)::coord
-            integer(c_size_t) :: coord_n
-            type(c_ptr), intent(out)::coordMaster
-            integer(c_size_t) :: coordMaster_n
-            integer(c_int), value::returnCoord
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetPeriodicKeys
-
-!  Import the model STL representation (if available) as the current mesh.
-        subroutine gmshModelMeshImportStl(
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshImportStl")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshImportStl
-
-!  Get the `tags' of any duplicate nodes in the mesh of the entities
-!  `dimTags'. If `dimTags' is empty, consider the whole mesh.
-        subroutine gmshModelMeshGetDuplicateNodes(
-     &      tags,
-     &      tags_n,
-     &      dimTags,
-     &      dimTags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshGetDuplicateNodes")
-          use, intrinsic :: iso_c_binding
-            type(c_ptr), intent(out)::tags
-            integer(c_size_t) :: tags_n
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshGetDuplicateNodes
-
-!  Remove duplicate nodes in the mesh of the entities `dimTags'. If `dimTags'
-!  is empty, consider the whole mesh.
-        subroutine gmshModelMeshRemoveDuplicateNodes(
-     &      dimTags,
-     &      dimTags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshRemoveDuplicateNodes")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshRemoveDuplicateNodes
-
-!  Remove duplicate elements (defined by the same nodes, in the same entity)
-!  in the mesh of the entities `dimTags'. If `dimTags' is empty, consider the
-!  whole mesh.
-        subroutine gmshModelMeshRemoveDuplicateElements(
-     &      dimTags,
-     &      dimTags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshRemoveDuplicateElements")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshRemoveDuplicateElements
-
-!  Split (into two triangles) all quadrangles in surface `tag' whose quality
-!  is lower than `quality'. If `tag' < 0, split quadrangles in all surfaces.
-        subroutine gmshModelMeshSplitQuadrangles(
-     &      quality,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshSplitQuadrangles")
-          use, intrinsic :: iso_c_binding
-            real(c_double), value::quality
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshSplitQuadrangles
-
-!  Set the visibility of the elements of tags `elementTags' to `value'.
-        subroutine gmshModelMeshSetVisibility(
-     &      elementTags,
-     &      elementTags_n,
-     &      value,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshSetVisibility")
-          use, intrinsic :: iso_c_binding
-            integer(c_size_t)::elementTags(*)
-            integer(c_size_t), value :: elementTags_n
-            integer(c_int), value::value
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshSetVisibility
-
-!  Classify ("color") the surface mesh based on the angle threshold `angle'
-!  (in radians), and create new discrete surfaces, curves and points
-!  accordingly. If `boundary' is set, also create discrete curves on the
-!  boundary if the surface is open. If `forReparametrization' is set, create
-!  curves and surfaces that can be reparametrized using a single map. If
-!  `curveAngle' is less than Pi, also force curves to be split according to
-!  `curveAngle'. If `exportDiscrete' is set, clear any built-in CAD kernel
-!  entities and export the discrete entities in the built-in CAD kernel.
-        subroutine gmshModelMeshClassifySurfaces(
-     &      angle,
-     &      boundary,
-     &      forReparametrization,
-     &      curveAngle,
-     &      exportDiscrete,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshClassifySurfaces")
-          use, intrinsic :: iso_c_binding
-            real(c_double), value::angle
-            integer(c_int), value::boundary
-            integer(c_int), value::forReparametrization
-            real(c_double), value::curveAngle
-            integer(c_int), value::exportDiscrete
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshClassifySurfaces
-
-!  Create a geometry for the discrete entities `dimTags' (represented solely
-!  by a mesh, without an underlying CAD description), i.e. create a
-!  parametrization for discrete curves and surfaces, assuming that each can be
-!  parametrized with a single map. If `dimTags' is empty, create a geometry
-!  for all the discrete entities.
-        subroutine gmshModelMeshCreateGeometry(
-     &      dimTags,
-     &      dimTags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshCreateGeometry")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshCreateGeometry
-
-!  Create a boundary representation from the mesh if the model does not have
-!  one (e.g. when imported from mesh file formats with no BRep representation
-!  of the underlying model). If `makeSimplyConnected' is set, enforce simply
-!  connected discrete surfaces and volumes. If `exportDiscrete' is set, clear
-!  any built-in CAD kernel entities and export the discrete entities in the
-!  built-in CAD kernel.
-        subroutine gmshModelMeshCreateTopology(
-     &      makeSimplyConnected,
-     &      exportDiscrete,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshCreateTopology")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::makeSimplyConnected
-            integer(c_int), value::exportDiscrete
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshCreateTopology
-
-!  Add a request to compute a basis representation for homology spaces (if
-!  `type' == "Homology") or cohomology spaces (if `type' == "Cohomology"). The
-!  computation domain is given in a list of physical group tags `domainTags';
-!  if empty, the whole mesh is the domain. The computation subdomain for
-!  relative (co)homology computation is given in a list of physical group tags
-!  `subdomainTags'; if empty, absolute (co)homology is computed. The
-!  dimensions of the (co)homology bases to be computed are given in the list
-!  `dim'; if empty, all bases are computed. Resulting basis representation
-!  (co)chains are stored as physical groups in the mesh. If the request is
-!  added before mesh generation, the computation will be performed at the end
-!  of the meshing pipeline.
-        subroutine gmshModelMeshAddHomologyRequest(
-     &      type,
-     &      domainTags,
-     &      domainTags_n,
-     &      subdomainTags,
-     &      subdomainTags_n,
-     &      dims,
-     &      dims_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshAddHomologyRequest")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::type(*)
-            integer(c_int)::domainTags(*)
-            integer(c_size_t), value :: domainTags_n
-            integer(c_int)::subdomainTags(*)
-            integer(c_size_t), value :: subdomainTags_n
-            integer(c_int)::dims(*)
-            integer(c_size_t), value :: dims_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshAddHomologyRequest
-
-!  Clear all (co)homology computation requests.
-        subroutine gmshModelMeshClearHomologyRequests(
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshClearHomologyRequests")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshClearHomologyRequests
-
-!  Perform the (co)homology computations requested by addHomologyRequest().
-!  The newly created physical groups are returned in `dimTags'.
-        subroutine gmshModelMeshComputeHomology(
-     &      dimTags,
-     &      dimTags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshComputeHomology")
-          use, intrinsic :: iso_c_binding
-            type(c_ptr), intent(out)::dimTags
-            integer(c_size_t) :: dimTags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshComputeHomology
-
-!  Compute a cross field for the current mesh. The function creates 3 views:
-!  the H function, the Theta function and cross directions. Return the tags of
-!  the views.
-        subroutine gmshModelMeshComputeCrossField(
-     &      viewTags,
-     &      viewTags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshComputeCrossField")
-          use, intrinsic :: iso_c_binding
-            type(c_ptr), intent(out)::viewTags
-            integer(c_size_t) :: viewTags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshComputeCrossField
-
-!  Triangulate the points given in the `coord' vector as pairs of u, v
-!  coordinates, and return the node tags (with numbering starting at 1) of the
-!  resulting triangles in `tri'.
-        subroutine gmshModelMeshTriangulate(
-     &      coord,
-     &      coord_n,
-     &      tri,
-     &      tri_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshTriangulate")
-          use, intrinsic :: iso_c_binding
-            real(c_double)::coord(*)
-            integer(c_size_t), value :: coord_n
-            type(c_ptr), intent(out)::tri
-            integer(c_size_t) :: tri_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshTriangulate
-
-!  Tetrahedralize the points given in the `coord' vector as triplets of x, y,
-!  z coordinates, and return the node tags (with numbering starting at 1) of
-!  the resulting tetrahedra in `tetra'.
-        subroutine gmshModelMeshTetrahedralize(
-     &      coord,
-     &      coord_n,
-     &      tetra,
-     &      tetra_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshTetrahedralize")
-          use, intrinsic :: iso_c_binding
-            real(c_double)::coord(*)
-            integer(c_size_t), value :: coord_n
-            type(c_ptr), intent(out)::tetra
-            integer(c_size_t) :: tetra_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshTetrahedralize
-
-!  Add a new mesh size field of type `fieldType'. If `tag' is positive, assign
-!  the tag explicitly; otherwise a new tag is assigned automatically. Return
-!  the field tag.
-        function gmshModelMeshFieldAdd(
-     &      fieldType,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshFieldAdd")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelMeshFieldAdd
-            character(len = 1, kind = c_char)::fieldType(*)
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end function gmshModelMeshFieldAdd
-
-!  Remove the field with tag `tag'.
-        subroutine gmshModelMeshFieldRemove(
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshFieldRemove")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshFieldRemove
-
-!  Get the list of all fields.
-        subroutine gmshModelMeshFieldList(
-     &      tags,
-     &      tags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshFieldList")
-          use, intrinsic :: iso_c_binding
-            type(c_ptr), intent(out)::tags
-            integer(c_size_t) :: tags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshFieldList
-
-!  Get the type `fieldType' of the field with tag `tag'.
-        subroutine gmshModelMeshFieldGetType(
-     &      tag,
-     &      fileType,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshFieldGetType")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            type(c_ptr)::fileType(*)
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshFieldGetType
-
-!  Set the numerical option `option' to value `value' for field `tag'.
-        subroutine gmshModelMeshFieldSetNumber(
-     &      tag,
-     &      option,
-     &      value,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshFieldSetNumber")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            character(len = 1, kind = c_char)::option(*)
-            real(c_double), value::value
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshFieldSetNumber
-
-!  Get the value of the numerical option `option' for field `tag'.
-        subroutine gmshModelMeshFieldGetNumber(
-     &      tag,
-     &      option,
-     &      value,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshFieldGetNumber")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            character(len = 1, kind = c_char)::option(*)
-            real(c_double)::value
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshFieldGetNumber
-
-!  Set the string option `option' to value `value' for field `tag'.
-        subroutine gmshModelMeshFieldSetString(
-     &      tag,
-     &      option,
-     &      value,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshFieldSetString")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            character(len = 1, kind = c_char)::option(*)
-            character(len = 1, kind = c_char)::value(*)
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshFieldSetString
-
-!  Get the value of the string option `option' for field `tag'.
-        subroutine gmshModelMeshFieldGetString(
-     &      tag,
-     &      option,
-     &      value,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshFieldGetString")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            character(len = 1, kind = c_char)::option(*)
-            type(c_ptr)::value(*)
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshFieldGetString
-
-!  Set the numerical list option `option' to value `value' for field `tag'.
-        subroutine gmshModelMeshFieldSetNumbers(
-     &      tag,
-     &      option,
-     &      value,
-     &      value_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshFieldSetNumbers")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            character(len = 1, kind = c_char)::option(*)
-            real(c_double)::value(*)
-            integer(c_size_t), value :: value_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshFieldSetNumbers
-
-!  Get the value of the numerical list option `option' for field `tag'.
-        subroutine gmshModelMeshFieldGetNumbers(
-     &      tag,
-     &      option,
-     &      value,
-     &      value_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshFieldGetNumbers")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            character(len = 1, kind = c_char)::option(*)
-            type(c_ptr), intent(out)::value
-            integer(c_size_t) :: value_n
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshFieldGetNumbers
-
-!  Set the field `tag' as the background mesh size field.
-        subroutine gmshModelMeshFieldSetAsBackgroundMesh(
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshFieldSetAsBackgroundMesh")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshFieldSetAsBackgroundMesh
-
-!  Set the field `tag' as a boundary layer size field.
-        subroutine gmshModelMeshFieldSetAsBoundaryLayer(
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelMeshFieldSetAsBoundaryLayer")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end subroutine gmshModelMeshFieldSetAsBoundaryLayer
-
-!  Add a geometrical point in the built-in CAD representation, at coordinates
-!  (`x', `y', `z'). If `meshSize' is > 0, add a meshing constraint at that
-!  point. If `tag' is positive, set the tag explicitly; otherwise a new tag is
-!  selected automatically. Return the tag of the point. (Note that the point
-!  will be added in the current model only after `synchronize' is called. This
-!  behavior holds for all the entities added in the geo module.)
-        function gmshModelGeoAddPoint(
-     &      x,
-     &      y,
-     &      z,
-     &      meshSize,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoAddPoint")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelGeoAddPoint
-            real(c_double), value::x
-            real(c_double), value::y
-            real(c_double), value::z
-            real(c_double), value::meshSize
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end function gmshModelGeoAddPoint
-
-!  Add a straight line segment in the built-in CAD representation, between the
-!  two points with tags `startTag' and `endTag'. If `tag' is positive, set the
-!  tag explicitly; otherwise a new tag is selected automatically. Return the
-!  tag of the line.
-        function gmshModelGeoAddLine(
-     &      startTag,
-     &      endTag,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoAddLine")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelGeoAddLine
-            integer(c_int), value::startTag
-            integer(c_int), value::endTag
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end function gmshModelGeoAddLine
-
-!  Add a circle arc (strictly smaller than Pi) in the built-in CAD
-!  representation, between the two points with tags `startTag' and `endTag',
-!  and with center `centerTag'. If `tag' is positive, set the tag explicitly;
-!  otherwise a new tag is selected automatically. If (`nx', `ny', `nz') != (0,
-!  0, 0), explicitly set the plane of the circle arc. Return the tag of the
-!  circle arc.
-        function gmshModelGeoAddCircleArc(
-     &      startTag,
-     &      centerTag,
-     &      endTag,
-     &      tag,
-     &      nx,
-     &      ny,
-     &      nz,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoAddCircleArc")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelGeoAddCircleArc
-            integer(c_int), value::startTag
-            integer(c_int), value::centerTag
-            integer(c_int), value::endTag
-            integer(c_int), value::tag
-            real(c_double), value::nx
-            real(c_double), value::ny
-            real(c_double), value::nz
-            integer(c_int)::ierr
-          end function gmshModelGeoAddCircleArc
-
-!  Add an ellipse arc (strictly smaller than Pi) in the built-in CAD
-!  representation, between the two points `startTag' and `endTag', and with
-!  center `centerTag' and major axis point `majorTag'. If `tag' is positive,
-!  set the tag explicitly; otherwise a new tag is selected automatically. If
-!  (`nx', `ny', `nz') != (0, 0, 0), explicitly set the plane of the circle
-!  arc. Return the tag of the ellipse arc.
-        function gmshModelGeoAddEllipseArc(
-     &      startTag,
-     &      centerTag,
-     &      majorTag,
-     &      endTag,
-     &      tag,
-     &      nx,
-     &      ny,
-     &      nz,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoAddEllipseArc")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelGeoAddEllipseArc
-            integer(c_int), value::startTag
-            integer(c_int), value::centerTag
-            integer(c_int), value::majorTag
-            integer(c_int), value::endTag
-            integer(c_int), value::tag
-            real(c_double), value::nx
-            real(c_double), value::ny
-            real(c_double), value::nz
-            integer(c_int)::ierr
-          end function gmshModelGeoAddEllipseArc
-
-!  Add a spline (Catmull-Rom) curve in the built-in CAD representation, going
-!  through the points `pointTags'. If `tag' is positive, set the tag
-!  explicitly; otherwise a new tag is selected automatically. Create a
-!  periodic curve if the first and last points are the same. Return the tag of
-!  the spline curve.
-        function gmshModelGeoAddSpline(
-     &      pointTags,
-     &      pointTags_n,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoAddSpline")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelGeoAddSpline
-            integer(c_int)::pointTags(*)
-            integer(c_size_t), value :: pointTags_n
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end function gmshModelGeoAddSpline
-
-!  Add a cubic b-spline curve in the built-in CAD representation, with
-!  `pointTags' control points. If `tag' is positive, set the tag explicitly;
-!  otherwise a new tag is selected automatically. Creates a periodic curve if
-!  the first and last points are the same. Return the tag of the b-spline
-!  curve.
-        function gmshModelGeoAddBSpline(
-     &      pointTags,
-     &      pointTags_n,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoAddBSpline")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelGeoAddBSpline
-            integer(c_int)::pointTags(*)
-            integer(c_size_t), value :: pointTags_n
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end function gmshModelGeoAddBSpline
-
-!  Add a Bezier curve in the built-in CAD representation, with `pointTags'
-!  control points. If `tag' is positive, set the tag explicitly; otherwise a
-!  new tag is selected automatically.  Return the tag of the Bezier curve.
-        function gmshModelGeoAddBezier(
-     &      pointTags,
-     &      pointTags_n,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoAddBezier")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelGeoAddBezier
-            integer(c_int)::pointTags(*)
-            integer(c_size_t), value :: pointTags_n
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end function gmshModelGeoAddBezier
-
-!  Add a polyline curve in the built-in CAD representation, going through the
-!  points `pointTags'. If `tag' is positive, set the tag explicitly; otherwise
-!  a new tag is selected automatically. Create a periodic curve if the first
-!  and last points are the same. Return the tag of the polyline curve.
-        function gmshModelGeoAddPolyline(
-     &      pointTags,
-     &      pointTags_n,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoAddPolyline")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelGeoAddPolyline
-            integer(c_int)::pointTags(*)
-            integer(c_size_t), value :: pointTags_n
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end function gmshModelGeoAddPolyline
-
-!  Add a spline (Catmull-Rom) curve in the built-in CAD representation, going
-!  through points sampling the curves in `curveTags'. The density of sampling
-!  points on each curve is governed by `numIntervals'. If `tag' is positive,
-!  set the tag explicitly; otherwise a new tag is selected automatically.
-!  Return the tag of the spline.
-        function gmshModelGeoAddCompoundSpline(
-     &      curveTags,
-     &      curveTags_n,
-     &      numIntervals,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoAddCompoundSpline")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelGeoAddCompoundSpline
-            integer(c_int)::curveTags(*)
-            integer(c_size_t), value :: curveTags_n
-            integer(c_int), value::numIntervals
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end function gmshModelGeoAddCompoundSpline
-
-!  Add a b-spline curve in the built-in CAD representation, with control
-!  points sampling the curves in `curveTags'. The density of sampling points
-!  on each curve is governed by `numIntervals'. If `tag' is positive, set the
-!  tag explicitly; otherwise a new tag is selected automatically. Return the
-!  tag of the b-spline.
-        function gmshModelGeoAddCompoundBSpline(
-     &      curveTags,
-     &      curveTags_n,
-     &      numIntervals,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoAddCompoundBSpline")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelGeoAddCompoundBSpline
-            integer(c_int)::curveTags(*)
-            integer(c_size_t), value :: curveTags_n
-            integer(c_int), value::numIntervals
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end function gmshModelGeoAddCompoundBSpline
-
-!  Add a curve loop (a closed wire) in the built-in CAD representation, formed
-!  by the curves `curveTags'. `curveTags' should contain (signed) tags of
-!  model entities of dimension 1 forming a closed loop: a negative tag
-!  signifies that the underlying curve is considered with reversed
-!  orientation. If `tag' is positive, set the tag explicitly; otherwise a new
-!  tag is selected automatically. If `reorient' is set, automatically reorient
-!  the curves if necessary. Return the tag of the curve loop.
-        function gmshModelGeoAddCurveLoop(
-     &      curveTags,
-     &      curveTags_n,
-     &      tag,
-     &      reorient,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoAddCurveLoop")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelGeoAddCurveLoop
-            integer(c_int)::curveTags(*)
-            integer(c_size_t), value :: curveTags_n
-            integer(c_int), value::tag
-            integer(c_int), value::reorient
-            integer(c_int)::ierr
-          end function gmshModelGeoAddCurveLoop
-
-!  Add curve loops in the built-in CAD representation based on the curves
-!  `curveTags'. Return the `tags' of found curve loops, if any.
-        subroutine gmshModelGeoAddCurveLoops(
-     &      curveTags,
-     &      curveTags_n,
-     &      tags,
-     &      tags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoAddCurveLoops")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::curveTags(*)
-            integer(c_size_t), value :: curveTags_n
-            type(c_ptr), intent(out)::tags
-            integer(c_size_t) :: tags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelGeoAddCurveLoops
-
-!  Add a plane surface in the built-in CAD representation, defined by one or
-!  more curve loops `wireTags'. The first curve loop defines the exterior
-!  contour; additional curve loop define holes. If `tag' is positive, set the
-!  tag explicitly; otherwise a new tag is selected automatically. Return the
-!  tag of the surface.
-        function gmshModelGeoAddPlaneSurface(
-     &      wireTags,
-     &      wireTags_n,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoAddPlaneSurface")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelGeoAddPlaneSurface
-            integer(c_int)::wireTags(*)
-            integer(c_size_t), value :: wireTags_n
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end function gmshModelGeoAddPlaneSurface
-
-!  Add a surface in the built-in CAD representation, filling the curve loops
-!  in `wireTags' using transfinite interpolation. Currently only a single
-!  curve loop is supported; this curve loop should be composed by 3 or 4
-!  curves only. If `tag' is positive, set the tag explicitly; otherwise a new
-!  tag is selected automatically. Return the tag of the surface.
-        function gmshModelGeoAddSurfaceFilling(
-     &      wireTags,
-     &      wireTags_n,
-     &      tag,
-     &      sphereCenterTag,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoAddSurfaceFilling")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelGeoAddSurfaceFilling
-            integer(c_int)::wireTags(*)
-            integer(c_size_t), value :: wireTags_n
-            integer(c_int), value::tag
-            integer(c_int), value::sphereCenterTag
-            integer(c_int)::ierr
-          end function gmshModelGeoAddSurfaceFilling
-
-!  Add a surface loop (a closed shell) formed by `surfaceTags' in the built-in
-!  CAD representation.  If `tag' is positive, set the tag explicitly;
-!  otherwise a new tag is selected automatically. Return the tag of the shell.
-        function gmshModelGeoAddSurfaceLoop(
-     &      surfaceTags,
-     &      surfaceTags_n,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoAddSurfaceLoop")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelGeoAddSurfaceLoop
-            integer(c_int)::surfaceTags(*)
-            integer(c_size_t), value :: surfaceTags_n
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end function gmshModelGeoAddSurfaceLoop
-
-!  Add a volume (a region) in the built-in CAD representation, defined by one
-!  or more shells `shellTags'. The first surface loop defines the exterior
-!  boundary; additional surface loop define holes. If `tag' is positive, set
-!  the tag explicitly; otherwise a new tag is selected automatically. Return
-!  the tag of the volume.
-        function gmshModelGeoAddVolume(
-     &      shellTags,
-     &      shellTags_n,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoAddVolume")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelGeoAddVolume
-            integer(c_int)::shellTags(*)
-            integer(c_size_t), value :: shellTags_n
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end function gmshModelGeoAddVolume
-
-!  Add a `geometry' in the built-in CAD representation. `geometry' can
-!  currently be one of "Sphere" or "PolarSphere" (where `numbers' should
-!  contain the x, y, z coordinates of the center, followed by the radius), or
-!  "Parametric" (where `strings' should contains three expression evaluating
-!  to the x, y and z coordinates. If `tag' is positive, set the tag of the
-!  geometry explicitly; otherwise a new tag is selected automatically. Return
-!  the tag of the geometry.
-        function gmshModelGeoAddGeometry(
-     &      geometry,
-     &      numbers,
-     &      numbers_n,
-     &      strings,
-     &      strings_n,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoAddGeometry")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelGeoAddGeometry
-            character(len = 1, kind = c_char)::geometry(*)
-            real(c_double)::numbers(*)
-            integer(c_size_t), value :: numbers_n
-            type(c_ptr)::strings(*)
-            integer(c_size_t), value :: strings_n
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end function gmshModelGeoAddGeometry
-
-!  Add a point in the built-in CAD representation, at coordinates (`x', `y',
-!  `z') on the geometry `geometryTag'. If `meshSize' is > 0, add a meshing
-!  constraint at that point. If `tag' is positive, set the tag explicitly;
-!  otherwise a new tag is selected automatically. Return the tag of the point.
-!  For surface geometries, only the `x' and `y' coordinates are used.
-        function gmshModelGeoAddPointOnGeometry(
-     &      geometryTag,
-     &      x,
-     &      y,
-     &      z,
-     &      meshSize,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoAddPointOnGeometry")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelGeoAddPointOnGeometry
-            integer(c_int), value::geometryTag
-            real(c_double), value::x
-            real(c_double), value::y
-            real(c_double), value::z
-            real(c_double), value::meshSize
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end function gmshModelGeoAddPointOnGeometry
-
-!  Extrude the entities `dimTags' in the built-in CAD representation, using a
-!  translation along (`dx', `dy', `dz'). Return 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 (cumulative) height of the different
-!  layers, normalized to 1. If `recombine' is set, recombine the mesh in the
-!  layers.
-        subroutine gmshModelGeoExtrude(
-     &      dimTags,
-     &      dimTags_n,
-     &      dx,
-     &      dy,
-     &      dz,
-     &      outDimTags,
-     &      outDimTags_n,
-     &      numElements,
-     &      numElements_n,
-     &      heights,
-     &      heights_n,
-     &      recombine,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoExtrude")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            real(c_double), value::dx
-            real(c_double), value::dy
-            real(c_double), value::dz
-            type(c_ptr), intent(out)::outDimTags
-            integer(c_size_t) :: outDimTags_n
-            integer(c_int)::numElements(*)
-            integer(c_size_t), value :: numElements_n
-            real(c_double)::heights(*)
-            integer(c_size_t), value :: heights_n
-            integer(c_int), value::recombine
-            integer(c_int)::ierr
-          end subroutine gmshModelGeoExtrude
-
-!  Extrude the entities `dimTags' in the built-in CAD representation, using a
-!  rotation of `angle' radians around the axis of revolution defined by the
-!  point (`x', `y', `z') and the direction (`ax', `ay', `az'). The angle
-!  should be strictly smaller than Pi. Return 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 (cumulative) height of the different
-!  layers, normalized to 1. If `recombine' is set, recombine the mesh in the
-!  layers.
-        subroutine gmshModelGeoRevolve(
-     &      dimTags,
-     &      dimTags_n,
-     &      x,
-     &      y,
-     &      z,
-     &      ax,
-     &      ay,
-     &      az,
-     &      angle,
-     &      outDimTags,
-     &      outDimTags_n,
-     &      numElements,
-     &      numElements_n,
-     &      heights,
-     &      heights_n,
-     &      recombine,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoRevolve")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            real(c_double), value::x
-            real(c_double), value::y
-            real(c_double), value::z
-            real(c_double), value::ax
-            real(c_double), value::ay
-            real(c_double), value::az
-            real(c_double), value::angle
-            type(c_ptr), intent(out)::outDimTags
-            integer(c_size_t) :: outDimTags_n
-            integer(c_int)::numElements(*)
-            integer(c_size_t), value :: numElements_n
-            real(c_double)::heights(*)
-            integer(c_size_t), value :: heights_n
-            integer(c_int), value::recombine
-            integer(c_int)::ierr
-          end subroutine gmshModelGeoRevolve
-
-!  Extrude the entities `dimTags' in the built-in CAD representation, using 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'). The angle should be strictly
-!  smaller than Pi. Return 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
-!  (cumulative) height of the different layers, normalized to 1. If
-!  `recombine' is set, recombine the mesh in the layers.
-        subroutine gmshModelGeoTwist(
-     &      dimTags,
-     &      dimTags_n,
-     &      x,
-     &      y,
-     &      z,
-     &      dx,
-     &      dy,
-     &      dz,
-     &      ax,
-     &      ay,
-     &      az,
-     &      angle,
-     &      outDimTags,
-     &      outDimTags_n,
-     &      numElements,
-     &      numElements_n,
-     &      heights,
-     &      heights_n,
-     &      recombine,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoTwist")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            real(c_double), value::x
-            real(c_double), value::y
-            real(c_double), value::z
-            real(c_double), value::dx
-            real(c_double), value::dy
-            real(c_double), value::dz
-            real(c_double), value::ax
-            real(c_double), value::ay
-            real(c_double), value::az
-            real(c_double), value::angle
-            type(c_ptr), intent(out)::outDimTags
-            integer(c_size_t) :: outDimTags_n
-            integer(c_int)::numElements(*)
-            integer(c_size_t), value :: numElements_n
-            real(c_double)::heights(*)
-            integer(c_size_t), value :: heights_n
-            integer(c_int), value::recombine
-            integer(c_int)::ierr
-          end subroutine gmshModelGeoTwist
-
-!  Extrude the entities `dimTags' in the built-in CAD representation along the
-!  normals of the mesh, creating discrete boundary layer entities. Return
-!  extruded entities in `outDimTags'. The entries in `numElements' give the
-!  number of elements in each layer. If `height' is not empty, it provides the
-!  (cumulative) height of the different layers. If `recombine' is set,
-!  recombine the mesh in the layers. A second boundary layer can be created
-!  from the same entities if `second' is set. If `viewIndex' is >= 0, use the
-!  corresponding view to either specify the normals (if the view contains a
-!  vector field) or scale the normals (if the view is scalar).
-        subroutine gmshModelGeoExtrudeBoundaryLayer(
-     &      dimTags,
-     &      dimTags_n,
-     &      outDimTags,
-     &      outDimTags_n,
-     &      numElements,
-     &      numElements_n,
-     &      heights,
-     &      heights_n,
-     &      recombine,
-     &      second,
-     &      viewIndex,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoExtrudeBoundaryLayer")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            type(c_ptr), intent(out)::outDimTags
-            integer(c_size_t) :: outDimTags_n
-            integer(c_int)::numElements(*)
-            integer(c_size_t), value :: numElements_n
-            real(c_double)::heights(*)
-            integer(c_size_t), value :: heights_n
-            integer(c_int), value::recombine
-            integer(c_int), value::second
-            integer(c_int), value::viewIndex
-            integer(c_int)::ierr
-          end subroutine gmshModelGeoExtrudeBoundaryLayer
-
-!  Translate the entities `dimTags' in the built-in CAD representation along
-!  (`dx', `dy', `dz').
-        subroutine gmshModelGeoTranslate(
-     &      dimTags,
-     &      dimTags_n,
-     &      dx,
-     &      dy,
-     &      dz,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoTranslate")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            real(c_double), value::dx
-            real(c_double), value::dy
-            real(c_double), value::dz
-            integer(c_int)::ierr
-          end subroutine gmshModelGeoTranslate
-
-!  Rotate the entities `dimTags' in the built-in CAD representation by `angle'
-!  radians around the axis of revolution defined by the point (`x', `y', `z')
-!  and the direction (`ax', `ay', `az').
-        subroutine gmshModelGeoRotate(
-     &      dimTags,
-     &      dimTags_n,
-     &      x,
-     &      y,
-     &      z,
-     &      ax,
-     &      ay,
-     &      az,
-     &      angle,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoRotate")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            real(c_double), value::x
-            real(c_double), value::y
-            real(c_double), value::z
-            real(c_double), value::ax
-            real(c_double), value::ay
-            real(c_double), value::az
-            real(c_double), value::angle
-            integer(c_int)::ierr
-          end subroutine gmshModelGeoRotate
-
-!  Scale the entities `dimTag' in the built-in CAD representation by factors
-!  `a', `b' and `c' along the three coordinate axes; use (`x', `y', `z') as
-!  the center of the homothetic transformation.
-        subroutine gmshModelGeoDilate(
-     &      dimTags,
-     &      dimTags_n,
-     &      x,
-     &      y,
-     &      z,
-     &      a,
-     &      b,
-     &      c,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoDilate")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            real(c_double), value::x
-            real(c_double), value::y
-            real(c_double), value::z
-            real(c_double), value::a
-            real(c_double), value::b
-            real(c_double), value::c
-            integer(c_int)::ierr
-          end subroutine gmshModelGeoDilate
-
-!  Mirror the entities `dimTag' in the built-in CAD representation, with
-!  respect to the plane of equation `a' * x + `b' * y + `c' * z + `d' = 0.
-        subroutine gmshModelGeoMirror(
-     &      dimTags,
-     &      dimTags_n,
-     &      a,
-     &      b,
-     &      c,
-     &      d,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoMirror")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            real(c_double), value::a
-            real(c_double), value::b
-            real(c_double), value::c
-            real(c_double), value::d
-            integer(c_int)::ierr
-          end subroutine gmshModelGeoMirror
-
-!  Mirror the entities `dimTag' in the built-in CAD representation, with
-!  respect to the plane of equation `a' * x + `b' * y + `c' * z + `d' = 0.
-!  (This is a synonym for `mirror', which will be deprecated in a future
-!  release.)
-        subroutine gmshModelGeoSymmetrize(
-     &      dimTags,
-     &      dimTags_n,
-     &      a,
-     &      b,
-     &      c,
-     &      d,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoSymmetrize")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            real(c_double), value::a
-            real(c_double), value::b
-            real(c_double), value::c
-            real(c_double), value::d
-            integer(c_int)::ierr
-          end subroutine gmshModelGeoSymmetrize
-
-!  Copy the entities `dimTags' in the built-in CAD representation; the new
-!  entities are returned in `outDimTags'.
-        subroutine gmshModelGeoCopy(
-     &      dimTags,
-     &      dimTags_n,
-     &      outDimTags,
-     &      outDimTags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoCopy")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            type(c_ptr), intent(out)::outDimTags
-            integer(c_size_t) :: outDimTags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelGeoCopy
-
-!  Remove the entities `dimTags' in the built-in CAD representation, provided
-!  that they are not on the boundary of higher-dimensional entities. If
-!  `recursive' is true, remove all the entities on their boundaries, down to
-!  dimension 0.
-        subroutine gmshModelGeoRemove(
-     &      dimTags,
-     &      dimTags_n,
-     &      recursive,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoRemove")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            integer(c_int), value::recursive
-            integer(c_int)::ierr
-          end subroutine gmshModelGeoRemove
-
-!  Remove all duplicate entities in the built-in CAD representation (different
-!  entities at the same geometrical location).
-        subroutine gmshModelGeoRemoveAllDuplicates(
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoRemoveAllDuplicates")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::ierr
-          end subroutine gmshModelGeoRemoveAllDuplicates
-
-!  Split the curve of tag `tag' in the built-in CAD representation, on the
-!  specified control points `pointTags'. This feature is only available for
-!  lines, splines and b-splines. Return the tag(s) `curveTags' of the newly
-!  created curve(s).
-        subroutine gmshModelGeoSplitCurve(
-     &      tag,
-     &      pointTags,
-     &      pointTags_n,
-     &      curveTags,
-     &      curveTags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoSplitCurve")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            integer(c_int)::pointTags(*)
-            integer(c_size_t), value :: pointTags_n
-            type(c_ptr), intent(out)::curveTags
-            integer(c_size_t) :: curveTags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelGeoSplitCurve
-
-!  Get the maximum tag of entities of dimension `dim' in the built-in CAD
-!  representation.
-        function gmshModelGeoGetMaxTag(
-     &      dim,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoGetMaxTag")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelGeoGetMaxTag
-            integer(c_int), value::dim
-            integer(c_int)::ierr
-          end function gmshModelGeoGetMaxTag
-
-!  Set the maximum tag `maxTag' for entities of dimension `dim' in the built-
-!  in CAD representation.
-        subroutine gmshModelGeoSetMaxTag(
-     &      dim,
-     &      maxTag,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoSetMaxTag")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::maxTag
-            integer(c_int)::ierr
-          end subroutine gmshModelGeoSetMaxTag
-
-!  Add a physical group of dimension `dim', grouping the entities with tags
-!  `tags' in the built-in CAD representation. Return the tag of the physical
-!  group, equal to `tag' if `tag' is positive, or a new tag if `tag' < 0. Set
-!  the name of the physical group if `name' is not empty.
-        function gmshModelGeoAddPhysicalGroup(
-     &      dim,
-     &      tags,
-     &      tags_n,
-     &      tag,
-     &      name,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoAddPhysicalGroup")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelGeoAddPhysicalGroup
-            integer(c_int), value::dim
-            integer(c_int)::tags(*)
-            integer(c_size_t), value :: tags_n
-            integer(c_int), value::tag
-            character(len = 1, kind = c_char)::name(*)
-            integer(c_int)::ierr
-          end function gmshModelGeoAddPhysicalGroup
-
-!  Remove the physical groups `dimTags' from the built-in CAD representation.
-!  If `dimTags' is empty, remove all groups.
-        subroutine gmshModelGeoRemovePhysicalGroups(
-     &      dimTags,
-     &      dimTags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoRemovePhysicalGroups")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelGeoRemovePhysicalGroups
-
-!  Synchronize the built-in 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. Without synchronization the entities in the built-in CAD
-!  representation are not available to any function outside of the built-in
-!  CAD kernel functions.
-        subroutine gmshModelGeoSynchronize(
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoSynchronize")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::ierr
-          end subroutine gmshModelGeoSynchronize
-
-!  Set a mesh size constraint on the entities `dimTags' in the built-in CAD
-!  kernel representation. Currently only entities of dimension 0 (points) are
-!  handled.
-        subroutine gmshModelGeoMeshSetSize(
-     &      dimTags,
-     &      dimTags_n,
-     &      size,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoMeshSetSize")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            real(c_double), value::size
-            integer(c_int)::ierr
-          end subroutine gmshModelGeoMeshSetSize
-
-!  Set a transfinite meshing constraint on the curve `tag' in the built-in CAD
-!  kernel representation, with `numNodes' nodes distributed according to
-!  `meshType' and `coef'. Currently supported types are "Progression"
-!  (geometrical progression with power `coef') and "Bump" (refinement toward
-!  both extremities of the curve).
-        subroutine gmshModelGeoMeshSetTransfiniteCurve(
-     &      tag,
-     &      nPoints,
-     &      meshType,
-     &      coef,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoMeshSetTransfiniteCurve")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            integer(c_int), value::nPoints
-            character(len = 1, kind = c_char)::meshType(*)
-            real(c_double), value::coef
-            integer(c_int)::ierr
-          end subroutine gmshModelGeoMeshSetTransfiniteCurve
-
-!  Set a transfinite meshing constraint on the surface `tag' in the built-in
-!  CAD kernel representation. `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.
-        subroutine gmshModelGeoMeshSetTransfiniteSurface(
-     &      tag,
-     &      arrangement,
-     &      cornerTags,
-     &      cornerTags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoMeshSetTransfiniteSurface")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            character(len = 1, kind = c_char)::arrangement(*)
-            integer(c_int)::cornerTags(*)
-            integer(c_size_t), value :: cornerTags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelGeoMeshSetTransfiniteSurface
-
-!  Set a transfinite meshing constraint on the surface `tag' in the built-in
-!  CAD kernel representation. `cornerTags' can be used to specify the (6 or 8)
-!  corners of the transfinite interpolation explicitly.
-        subroutine gmshModelGeoMeshSetTransfiniteVolume(
-     &      tag,
-     &      cornerTags,
-     &      cornerTags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoMeshSetTransfiniteVolume")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            integer(c_int)::cornerTags(*)
-            integer(c_size_t), value :: cornerTags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelGeoMeshSetTransfiniteVolume
-
-!  Set a recombination meshing constraint on the entity of dimension `dim' and
-!  tag `tag' in the built-in CAD kernel representation. Currently only
-!  entities of dimension 2 (to recombine triangles into quadrangles) are
-!  supported; `angle' specifies the threshold angle for the simple
-!  recombination algorithm.
-        subroutine gmshModelGeoMeshSetRecombine(
-     &      dim,
-     &      tag,
-     &      angle,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoMeshSetRecombine")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            real(c_double), value::angle
-            integer(c_int)::ierr
-          end subroutine gmshModelGeoMeshSetRecombine
-
-!  Set a smoothing meshing constraint on the entity of dimension `dim' and tag
-!  `tag' in the built-in CAD kernel representation. `val' iterations of a
-!  Laplace smoother are applied.
-        subroutine gmshModelGeoMeshSetSmoothing(
-     &      dim,
-     &      tag,
-     &      val,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoMeshSetSmoothing")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            integer(c_int), value::val
-            integer(c_int)::ierr
-          end subroutine gmshModelGeoMeshSetSmoothing
-
-!  Set a reverse meshing constraint on the entity of dimension `dim' and tag
-!  `tag' in the built-in CAD kernel representation. 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 geometry). If
-!  `val' is false, the mesh is left as-is.
-        subroutine gmshModelGeoMeshSetReverse(
-     &      dim,
-     &      tag,
-     &      val,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoMeshSetReverse")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            integer(c_int), value::val
-            integer(c_int)::ierr
-          end subroutine gmshModelGeoMeshSetReverse
-
-!  Set the meshing algorithm on the entity of dimension `dim' and tag `tag' in
-!  the built-in CAD kernel representation. Currently only supported for `dim'
-!  == 2.
-        subroutine gmshModelGeoMeshSetAlgorithm(
-     &      dim,
-     &      tag,
-     &      val,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoMeshSetAlgorithm")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            integer(c_int), value::val
-            integer(c_int)::ierr
-          end subroutine gmshModelGeoMeshSetAlgorithm
-
-!  Force the mesh size to be extended from the boundary, or not, for the
-!  entity of dimension `dim' and tag `tag' in the built-in CAD kernel
-!  representation. Currently only supported for `dim' == 2.
-        subroutine gmshModelGeoMeshSetSizeFromBoundary(
-     &      dim,
-     &      tag,
-     &      val,
-     &      ierr)
-     &    bind(C, name = "gmshModelGeoMeshSetSizeFromBoundary")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            integer(c_int), value::val
-            integer(c_int)::ierr
-          end subroutine gmshModelGeoMeshSetSizeFromBoundary
-
-!  Add a geometrical point in the OpenCASCADE CAD representation, at
-!  coordinates (`x', `y', `z'). If `meshSize' is > 0, add a meshing constraint
-!  at that point. If `tag' is positive, set the tag explicitly; otherwise a
-!  new tag is selected automatically. Return the tag of the point. (Note that
-!  the point will be added in the current model only after `synchronize' is
-!  called. This behavior holds for all the entities added in the occ module.)
-        function gmshModelOccAddPoint(
-     &      x,
-     &      y,
-     &      z,
-     &      meshSize,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAddPoint")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelOccAddPoint
-            real(c_double), value::x
-            real(c_double), value::y
-            real(c_double), value::z
-            real(c_double), value::meshSize
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end function gmshModelOccAddPoint
-
-!  Add a straight line segment in the OpenCASCADE CAD representation, between
-!  the two points with tags `startTag' and `endTag'. If `tag' is positive, set
-!  the tag explicitly; otherwise a new tag is selected automatically. Return
-!  the tag of the line.
-        function gmshModelOccAddLine(
-     &      startTag,
-     &      endTag,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAddLine")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelOccAddLine
-            integer(c_int), value::startTag
-            integer(c_int), value::endTag
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end function gmshModelOccAddLine
-
-!  Add a circle arc in the OpenCASCADE CAD representation, between the two
-!  points with tags `startTag' and `endTag', with center `centerTag'. If `tag'
-!  is positive, set the tag explicitly; otherwise a new tag is selected
-!  automatically. Return the tag of the circle arc.
-        function gmshModelOccAddCircleArc(
-     &      startTag,
-     &      centerTag,
-     &      endTag,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAddCircleArc")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelOccAddCircleArc
-            integer(c_int), value::startTag
-            integer(c_int), value::centerTag
-            integer(c_int), value::endTag
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end function gmshModelOccAddCircleArc
-
-!  Add a circle of center (`x', `y', `z') and radius `r' in the OpenCASCADE
-!  CAD representation. If `tag' is positive, set the tag explicitly; otherwise
-!  a new tag is selected automatically. If `angle1' and `angle2' are
-!  specified, create a circle arc between the two angles. If a vector `zAxis'
-!  of size 3 is provided, use it as the normal to the circle plane (z-axis).
-!  If a vector `xAxis' of size 3 is provided in addition to `zAxis', use it to
-!  define the x-axis. Return the tag of the circle.
-        function gmshModelOccAddCircle(
-     &      x,
-     &      y,
-     &      z,
-     &      r,
-     &      tag,
-     &      angle1,
-     &      angle2,
-     &      zAxis,
-     &      zAxis_n,
-     &      xAxis,
-     &      xAxis_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAddCircle")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelOccAddCircle
-            real(c_double), value::x
-            real(c_double), value::y
-            real(c_double), value::z
-            real(c_double), value::r
-            integer(c_int), value::tag
-            real(c_double), value::angle1
-            real(c_double), value::angle2
-            real(c_double)::zAxis(*)
-            integer(c_size_t), value :: zAxis_n
-            real(c_double)::xAxis(*)
-            integer(c_size_t), value :: xAxis_n
-            integer(c_int)::ierr
-          end function gmshModelOccAddCircle
-
-!  Add an ellipse arc in the OpenCASCADE CAD representation, between the two
-!  points `startTag' and `endTag', and with center `centerTag' and major axis
-!  point `majorTag'. If `tag' is positive, set the tag explicitly; otherwise a
-!  new tag is selected automatically. Return the tag of the ellipse arc. Note
-!  that OpenCASCADE does not allow creating ellipse arcs with the major radius
-!  smaller than the minor radius.
-        function gmshModelOccAddEllipseArc(
-     &      startTag,
-     &      centerTag,
-     &      majorTag,
-     &      endTag,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAddEllipseArc")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelOccAddEllipseArc
-            integer(c_int), value::startTag
-            integer(c_int), value::centerTag
-            integer(c_int), value::majorTag
-            integer(c_int), value::endTag
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end function gmshModelOccAddEllipseArc
-
-!  Add an ellipse of center (`x', `y', `z') and radii `r1' and `r2' (with `r1'
-!  >= `r2') along the x- and y-axes, respectively, in the OpenCASCADE CAD
-!  representation. If `tag' is positive, set the tag explicitly; otherwise a
-!  new tag is selected automatically. If `angle1' and `angle2' are specified,
-!  create an ellipse arc between the two angles. If a vector `zAxis' of size 3
-!  is provided, use it as the normal to the ellipse plane (z-axis). If a
-!  vector `xAxis' of size 3 is provided in addition to `zAxis', use it to
-!  define the x-axis. Return the tag of the ellipse.
-        function gmshModelOccAddEllipse(
-     &      x,
-     &      y,
-     &      z,
-     &      r1,
-     &      r2,
-     &      tag,
-     &      angle1,
-     &      angle2,
-     &      zAxis,
-     &      zAxis_n,
-     &      xAxis,
-     &      xAxis_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAddEllipse")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelOccAddEllipse
-            real(c_double), value::x
-            real(c_double), value::y
-            real(c_double), value::z
-            real(c_double), value::r1
-            real(c_double), value::r2
-            integer(c_int), value::tag
-            real(c_double), value::angle1
-            real(c_double), value::angle2
-            real(c_double)::zAxis(*)
-            integer(c_size_t), value :: zAxis_n
-            real(c_double)::xAxis(*)
-            integer(c_size_t), value :: xAxis_n
-            integer(c_int)::ierr
-          end function gmshModelOccAddEllipse
-
-!  Add a spline (C2 b-spline) curve in the OpenCASCADE CAD representation,
-!  going through the points `pointTags'. If `tag' is positive, set the tag
-!  explicitly; otherwise a new tag is selected automatically. Create a
-!  periodic curve if the first and last points are the same. Return the tag of
-!  the spline curve.
-        function gmshModelOccAddSpline(
-     &      pointTags,
-     &      pointTags_n,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAddSpline")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelOccAddSpline
-            integer(c_int)::pointTags(*)
-            integer(c_size_t), value :: pointTags_n
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end function gmshModelOccAddSpline
-
-!  Add a b-spline curve of degree `degree' in the OpenCASCADE CAD
-!  representation, with `pointTags' control points. If `weights', `knots' or
-!  `multiplicities' are not provided, default parameters are computed
-!  automatically. If `tag' is positive, set the tag explicitly; otherwise a
-!  new tag is selected automatically. Create a periodic curve if the first and
-!  last points are the same. Return the tag of the b-spline curve.
-        function gmshModelOccAddBSpline(
-     &      pointTags,
-     &      pointTags_n,
-     &      tag,
-     &      degree,
-     &      weights,
-     &      weights_n,
-     &      knots,
-     &      knots_n,
-     &      multiplicities,
-     &      multiplicities_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAddBSpline")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelOccAddBSpline
-            integer(c_int)::pointTags(*)
-            integer(c_size_t), value :: pointTags_n
-            integer(c_int), value::tag
-            integer(c_int), value::degree
-            real(c_double)::weights(*)
-            integer(c_size_t), value :: weights_n
-            real(c_double)::knots(*)
-            integer(c_size_t), value :: knots_n
-            integer(c_int)::multiplicities(*)
-            integer(c_size_t), value :: multiplicities_n
-            integer(c_int)::ierr
-          end function gmshModelOccAddBSpline
-
-!  Add a Bezier curve in the OpenCASCADE CAD representation, with `pointTags'
-!  control points. If `tag' is positive, set the tag explicitly; otherwise a
-!  new tag is selected automatically. Return the tag of the Bezier curve.
-        function gmshModelOccAddBezier(
-     &      pointTags,
-     &      pointTags_n,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAddBezier")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelOccAddBezier
-            integer(c_int)::pointTags(*)
-            integer(c_size_t), value :: pointTags_n
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end function gmshModelOccAddBezier
-
-!  Add a wire (open or closed) in the OpenCASCADE CAD representation, formed
-!  by the curves `curveTags'. Note that an OpenCASCADE wire can be made of
-!  curves that share geometrically identical (but topologically different)
-!  points. If `tag' is positive, set the tag explicitly; otherwise a new tag
-!  is selected automatically. Return the tag of the wire.
-        function gmshModelOccAddWire(
-     &      curveTags,
-     &      curveTags_n,
-     &      tag,
-     &      checkClosed,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAddWire")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelOccAddWire
-            integer(c_int)::curveTags(*)
-            integer(c_size_t), value :: curveTags_n
-            integer(c_int), value::tag
-            integer(c_int), value::checkClosed
-            integer(c_int)::ierr
-          end function gmshModelOccAddWire
-
-!  Add a curve loop (a closed wire) in the OpenCASCADE CAD representation,
-!  formed by the curves `curveTags'. `curveTags' should contain tags of curves
-!  forming a closed loop. Negative tags can be specified for compatibility
-!  with the built-in kernel, but are simply ignored: the wire is oriented
-!  according to the orientation of its first curve. Note that an OpenCASCADE
-!  curve loop can be made of curves that share geometrically identical (but
-!  topologically different) points. If `tag' is positive, set the tag
-!  explicitly; otherwise a new tag is selected automatically. Return the tag
-!  of the curve loop.
-        function gmshModelOccAddCurveLoop(
-     &      curveTags,
-     &      curveTags_n,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAddCurveLoop")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelOccAddCurveLoop
-            integer(c_int)::curveTags(*)
-            integer(c_size_t), value :: curveTags_n
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end function gmshModelOccAddCurveLoop
-
-!  Add a rectangle in the OpenCASCADE CAD representation, with lower left
-!  corner at (`x', `y', `z') and upper right corner at (`x' + `dx', `y' +
-!  `dy', `z'). If `tag' is positive, set the tag explicitly; otherwise a new
-!  tag is selected automatically. Round the corners if `roundedRadius' is
-!  nonzero. Return the tag of the rectangle.
-        function gmshModelOccAddRectangle(
-     &      x,
-     &      y,
-     &      z,
-     &      dx,
-     &      dy,
-     &      tag,
-     &      roundedRadius,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAddRectangle")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelOccAddRectangle
-            real(c_double), value::x
-            real(c_double), value::y
-            real(c_double), value::z
-            real(c_double), value::dx
-            real(c_double), value::dy
-            integer(c_int), value::tag
-            real(c_double), value::roundedRadius
-            integer(c_int)::ierr
-          end function gmshModelOccAddRectangle
-
-!  Add a disk in the OpenCASCADE CAD representation, with center (`xc', `yc',
-!  `zc') and radius `rx' along the x-axis and `ry' along the y-axis (`rx' >=
-!  `ry'). If `tag' is positive, set the tag explicitly; otherwise a new tag is
-!  selected automatically. If a vector `zAxis' of size 3 is provided, use it
-!  as the normal to the disk (z-axis). If a vector `xAxis' of size 3 is
-!  provided in addition to `zAxis', use it to define the x-axis. Return the
-!  tag of the disk.
-        function gmshModelOccAddDisk(
-     &      xc,
-     &      yc,
-     &      zc,
-     &      rx,
-     &      ry,
-     &      tag,
-     &      zAxis,
-     &      zAxis_n,
-     &      xAxis,
-     &      xAxis_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAddDisk")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelOccAddDisk
-            real(c_double), value::xc
-            real(c_double), value::yc
-            real(c_double), value::zc
-            real(c_double), value::rx
-            real(c_double), value::ry
-            integer(c_int), value::tag
-            real(c_double)::zAxis(*)
-            integer(c_size_t), value :: zAxis_n
-            real(c_double)::xAxis(*)
-            integer(c_size_t), value :: xAxis_n
-            integer(c_int)::ierr
-          end function gmshModelOccAddDisk
-
-!  Add a plane surface in the OpenCASCADE CAD representation, defined by one
-!  or more curve loops (or closed wires) `wireTags'. The first curve loop
-!  defines the exterior contour; additional curve loop define holes. If `tag'
-!  is positive, set the tag explicitly; otherwise a new tag is selected
-!  automatically. Return the tag of the surface.
-        function gmshModelOccAddPlaneSurface(
-     &      wireTags,
-     &      wireTags_n,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAddPlaneSurface")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelOccAddPlaneSurface
-            integer(c_int)::wireTags(*)
-            integer(c_size_t), value :: wireTags_n
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end function gmshModelOccAddPlaneSurface
-
-!  Add a surface in the OpenCASCADE CAD representation, filling the curve loop
-!  `wireTag'. If `tag' is positive, set the tag explicitly; otherwise a new
-!  tag is selected automatically. Return the tag of the surface. If
-!  `pointTags' are provided, force the surface to pass through the given
-!  points. The other optional arguments are `degree' (the degree of the energy
-!  criterion to minimize for computing the deformation of the surface),
-!  `numPointsOnCurves' (the average number of points for discretisation of the
-!  bounding curves), `numIter' (the maximum number of iterations of the
-!  optimization process), `anisotropic' (improve performance when the ratio of
-!  the length along the two parametric coordinates of the surface is high),
-!  `tol2d' (tolerance to the constraints in the parametric plane of the
-!  surface), `tol3d' (the maximum distance allowed between the support surface
-!  and the constraints), `tolAng' (the maximum angle allowed between the
-!  normal of the surface and the constraints), `tolCurv' (the maximum
-!  difference of curvature allowed between the surface and the constraint),
-!  `maxDegree' (the highest degree which the polynomial defining the filling
-!  surface can have) and, `maxSegments' (the largest number of segments which
-!  the filling surface can have).
-        function gmshModelOccAddSurfaceFilling(
-     &      wireTag,
-     &      tag,
-     &      pointTags,
-     &      pointTags_n,
-     &      degree,
-     &      numPointsOnCurves,
-     &      numIter,
-     &      anisotropic,
-     &      tol2d,
-     &      tol3d,
-     &      tolAng,
-     &      tolCurv,
-     &      maxDegree,
-     &      maxSegments,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAddSurfaceFilling")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelOccAddSurfaceFilling
-            integer(c_int), value::wireTag
-            integer(c_int), value::tag
-            integer(c_int)::pointTags(*)
-            integer(c_size_t), value :: pointTags_n
-            integer(c_int), value::degree
-            integer(c_int), value::numPointsOnCurves
-            integer(c_int), value::numIter
-            integer(c_int), value::anisotropic
-            real(c_double), value::tol2d
-            real(c_double), value::tol3d
-            real(c_double), value::tolAng
-            real(c_double), value::tolCurv
-            integer(c_int), value::maxDegree
-            integer(c_int), value::maxSegments
-            integer(c_int)::ierr
-          end function gmshModelOccAddSurfaceFilling
-
-!  Add a BSpline surface in the OpenCASCADE CAD representation, filling the
-!  curve loop `wireTag'. The curve loop should be made of 2, 3 or 4 curves.
-!  The optional `type' argument specifies the type of filling: "Stretch"
-!  creates the flattest patch, "Curved" (the default) creates the most rounded
-!  patch, and "Coons" creates a rounded patch with less depth than "Curved".
-!  If `tag' is positive, set the tag explicitly; otherwise a new tag is
-!  selected automatically. Return the tag of the surface.
-        function gmshModelOccAddBSplineFilling(
-     &      wireTag,
-     &      tag,
-     &      type,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAddBSplineFilling")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelOccAddBSplineFilling
-            integer(c_int), value::wireTag
-            integer(c_int), value::tag
-            character(len = 1, kind = c_char)::type(*)
-            integer(c_int)::ierr
-          end function gmshModelOccAddBSplineFilling
-
-!  Add a Bezier surface in the OpenCASCADE CAD representation, filling the
-!  curve loop `wireTag'. The curve loop should be made of 2, 3 or 4 Bezier
-!  curves. The optional `type' argument specifies the type of filling:
-!  "Stretch" creates the flattest patch, "Curved" (the default) creates the
-!  most rounded patch, and "Coons" creates a rounded patch with less depth
-!  than "Curved". If `tag' is positive, set the tag explicitly; otherwise a
-!  new tag is selected automatically. Return the tag of the surface.
-        function gmshModelOccAddBezierFilling(
-     &      wireTag,
-     &      tag,
-     &      type,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAddBezierFilling")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelOccAddBezierFilling
-            integer(c_int), value::wireTag
-            integer(c_int), value::tag
-            character(len = 1, kind = c_char)::type(*)
-            integer(c_int)::ierr
-          end function gmshModelOccAddBezierFilling
-
-!  Add a b-spline surface of degree `degreeU' x `degreeV' in the OpenCASCADE
-!  CAD representation, with `pointTags' control points given as a single
-!  vector [Pu1v1, ... Pu`numPointsU'v1, Pu1v2, ...]. If `weights', `knotsU',
-!  `knotsV', `multiplicitiesU' or `multiplicitiesV' are not provided, default
-!  parameters are computed automatically. If `tag' is positive, set the tag
-!  explicitly; otherwise a new tag is selected automatically. If `wireTags' is
-!  provided, trim the b-spline patch using the provided wires: the first wire
-!  defines the external contour, the others define holes. If `wire3D' is set,
-!  consider wire curves as 3D curves and project them on the b-spline surface;
-!  otherwise consider the wire curves as defined in the parametric space of
-!  the surface. Return the tag of the b-spline surface.
-        function gmshModelOccAddBSplineSurface(
-     &      pointTags,
-     &      pointTags_n,
-     &      numPointsU,
-     &      tag,
-     &      degreeU,
-     &      degreeV,
-     &      weights,
-     &      weights_n,
-     &      knotsU,
-     &      knotsU_n,
-     &      knotsV,
-     &      knotsV_n,
-     &      multiplicitiesU,
-     &      multiplicitiesU_n,
-     &      multiplicitiesV,
-     &      multiplicitiesV_n,
-     &      wireTags,
-     &      wireTags_n,
-     &      wire3D,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAddBSplineSurface")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelOccAddBSplineSurface
-            integer(c_int)::pointTags(*)
-            integer(c_size_t), value :: pointTags_n
-            integer(c_int), value::numPointsU
-            integer(c_int), value::tag
-            integer(c_int), value::degreeU
-            integer(c_int), value::degreeV
-            real(c_double)::weights(*)
-            integer(c_size_t), value :: weights_n
-            real(c_double)::knotsU(*)
-            integer(c_size_t), value :: knotsU_n
-            real(c_double)::knotsV(*)
-            integer(c_size_t), value :: knotsV_n
-            integer(c_int)::multiplicitiesU(*)
-            integer(c_size_t), value :: multiplicitiesU_n
-            integer(c_int)::multiplicitiesV(*)
-            integer(c_size_t), value :: multiplicitiesV_n
-            integer(c_int)::wireTags(*)
-            integer(c_size_t), value :: wireTags_n
-            integer(c_int), value::wire3D
-            integer(c_int)::ierr
-          end function gmshModelOccAddBSplineSurface
-
-!  Add a Bezier surface in the OpenCASCADE CAD representation, with
-!  `pointTags' control points given as a single vector [Pu1v1, ...
-!  Pu`numPointsU'v1, Pu1v2, ...]. If `tag' is positive, set the tag
-!  explicitly; otherwise a new tag is selected automatically. If `wireTags' is
-!  provided, trim the Bezier patch using the provided wires: the first wire
-!  defines the external contour, the others define holes. If `wire3D' is set,
-!  consider wire curves as 3D curves and project them on the Bezier surface;
-!  otherwise consider the wire curves as defined in the parametric space of
-!  the surface. Return the tag of the Bezier surface.
-        function gmshModelOccAddBezierSurface(
-     &      pointTags,
-     &      pointTags_n,
-     &      numPointsU,
-     &      tag,
-     &      wireTags,
-     &      wireTags_n,
-     &      wire3D,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAddBezierSurface")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelOccAddBezierSurface
-            integer(c_int)::pointTags(*)
-            integer(c_size_t), value :: pointTags_n
-            integer(c_int), value::numPointsU
-            integer(c_int), value::tag
-            integer(c_int)::wireTags(*)
-            integer(c_size_t), value :: wireTags_n
-            integer(c_int), value::wire3D
-            integer(c_int)::ierr
-          end function gmshModelOccAddBezierSurface
-
-!  Trim the surface `surfaceTag' with the wires `wireTags', replacing any
-!  existing trimming curves. The first wire defines the external contour, the
-!  others define holes. If `wire3D' is set, consider wire curves as 3D curves
-!  and project them on the surface; otherwise consider the wire curves as
-!  defined in the parametric space of the surface. If `tag' is positive, set
-!  the tag explicitly; otherwise a new tag is selected automatically. Return
-!  the tag of the trimmed surface.
-        function gmshModelOccAddTrimmedSurface(
-     &      surfaceTag,
-     &      wireTags,
-     &      wireTags_n,
-     &      wire3D,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAddTrimmedSurface")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelOccAddTrimmedSurface
-            integer(c_int), value::surfaceTag
-            integer(c_int)::wireTags(*)
-            integer(c_size_t), value :: wireTags_n
-            integer(c_int), value::wire3D
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end function gmshModelOccAddTrimmedSurface
-
-!  Add a surface loop (a closed shell) in the OpenCASCADE CAD representation,
-!  formed by `surfaceTags'.  If `tag' is positive, set the tag explicitly;
-!  otherwise a new tag is selected automatically. Return the tag of the
-!  surface loop. Setting `sewing' allows one to build a shell made of surfaces
-!  that share geometrically identical (but topologically different) curves.
-        function gmshModelOccAddSurfaceLoop(
-     &      surfaceTags,
-     &      surfaceTags_n,
-     &      tag,
-     &      sewing,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAddSurfaceLoop")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelOccAddSurfaceLoop
-            integer(c_int)::surfaceTags(*)
-            integer(c_size_t), value :: surfaceTags_n
-            integer(c_int), value::tag
-            integer(c_int), value::sewing
-            integer(c_int)::ierr
-          end function gmshModelOccAddSurfaceLoop
-
-!  Add a volume (a region) in the OpenCASCADE CAD representation, 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, set the tag explicitly; otherwise a new tag is selected
-!  automatically. Return the tag of the volume.
-        function gmshModelOccAddVolume(
-     &      shellTags,
-     &      shellTags_n,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAddVolume")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelOccAddVolume
-            integer(c_int)::shellTags(*)
-            integer(c_size_t), value :: shellTags_n
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end function gmshModelOccAddVolume
-
-!  Add a sphere of center (`xc', `yc', `zc') and radius `r' in the OpenCASCADE
-!  CAD representation. The optional `angle1' and `angle2' arguments define the
-!  polar angle opening (from -Pi/2 to Pi/2). The optional `angle3' argument
-!  defines the azimuthal opening (from 0 to 2*Pi). If `tag' is positive, set
-!  the tag explicitly; otherwise a new tag is selected automatically. Return
-!  the tag of the sphere.
-        function gmshModelOccAddSphere(
-     &      xc,
-     &      yc,
-     &      zc,
-     &      radius,
-     &      tag,
-     &      angle1,
-     &      angle2,
-     &      angle3,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAddSphere")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelOccAddSphere
-            real(c_double), value::xc
-            real(c_double), value::yc
-            real(c_double), value::zc
-            real(c_double), value::radius
-            integer(c_int), value::tag
-            real(c_double), value::angle1
-            real(c_double), value::angle2
-            real(c_double), value::angle3
-            integer(c_int)::ierr
-          end function gmshModelOccAddSphere
-
-!  Add a parallelepipedic box in the OpenCASCADE CAD representation, defined
-!  by a point (`x', `y', `z') and the extents along the x-, y- and z-axes. If
-!  `tag' is positive, set the tag explicitly; otherwise a new tag is selected
-!  automatically. Return the tag of the box.
-        function gmshModelOccAddBox(
-     &      x,
-     &      y,
-     &      z,
-     &      dx,
-     &      dy,
-     &      dz,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAddBox")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelOccAddBox
-            real(c_double), value::x
-            real(c_double), value::y
-            real(c_double), value::z
-            real(c_double), value::dx
-            real(c_double), value::dy
-            real(c_double), value::dz
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end function gmshModelOccAddBox
-
-!  Add a cylinder in the OpenCASCADE CAD representation, defined by the center
-!  (`x', `y', `z') of its first circular face, the 3 components (`dx', `dy',
-!  `dz') of the vector defining its axis and its radius `r'. The optional
-!  `angle' argument defines the angular opening (from 0 to 2*Pi). If `tag' is
-!  positive, set the tag explicitly; otherwise a new tag is selected
-!  automatically. Return the tag of the cylinder.
-        function gmshModelOccAddCylinder(
-     &      x,
-     &      y,
-     &      z,
-     &      dx,
-     &      dy,
-     &      dz,
-     &      r,
-     &      tag,
-     &      angle,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAddCylinder")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelOccAddCylinder
-            real(c_double), value::x
-            real(c_double), value::y
-            real(c_double), value::z
-            real(c_double), value::dx
-            real(c_double), value::dy
-            real(c_double), value::dz
-            real(c_double), value::r
-            integer(c_int), value::tag
-            real(c_double), value::angle
-            integer(c_int)::ierr
-          end function gmshModelOccAddCylinder
-
-!  Add a cone in the OpenCASCADE CAD representation, defined by the center
-!  (`x', `y', `z') of its first circular face, the 3 components of the vector
-!  (`dx', `dy', `dz') defining its axis and the two radii `r1' and `r2' of the
-!  faces (these radii can be zero). If `tag' is positive, set the tag
-!  explicitly; otherwise a new tag is selected automatically. `angle' defines
-!  the optional angular opening (from 0 to 2*Pi). Return the tag of the cone.
-        function gmshModelOccAddCone(
-     &      x,
-     &      y,
-     &      z,
-     &      dx,
-     &      dy,
-     &      dz,
-     &      r1,
-     &      r2,
-     &      tag,
-     &      angle,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAddCone")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelOccAddCone
-            real(c_double), value::x
-            real(c_double), value::y
-            real(c_double), value::z
-            real(c_double), value::dx
-            real(c_double), value::dy
-            real(c_double), value::dz
-            real(c_double), value::r1
-            real(c_double), value::r2
-            integer(c_int), value::tag
-            real(c_double), value::angle
-            integer(c_int)::ierr
-          end function gmshModelOccAddCone
-
-!  Add a right angular wedge in the OpenCASCADE CAD representation, defined by
-!  the right-angle point (`x', `y', `z') and the 3 extends along the x-, y-
-!  and z-axes (`dx', `dy', `dz'). If `tag' is positive, set the tag
-!  explicitly; otherwise a new tag is selected automatically. The optional
-!  argument `ltx' defines the top extent along the x-axis. If a vector `zAxis'
-!  of size 3 is provided, use it to define the z-axis. Return the tag of the
-!  wedge.
-        function gmshModelOccAddWedge(
-     &      x,
-     &      y,
-     &      z,
-     &      dx,
-     &      dy,
-     &      dz,
-     &      tag,
-     &      ltx,
-     &      zAxis,
-     &      zAxis_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAddWedge")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelOccAddWedge
-            real(c_double), value::x
-            real(c_double), value::y
-            real(c_double), value::z
-            real(c_double), value::dx
-            real(c_double), value::dy
-            real(c_double), value::dz
-            integer(c_int), value::tag
-            real(c_double), value::ltx
-            real(c_double)::zAxis(*)
-            integer(c_size_t), value :: zAxis_n
-            integer(c_int)::ierr
-          end function gmshModelOccAddWedge
-
-!  Add a torus in the OpenCASCADE CAD representation, defined by its center
-!  (`x', `y', `z') and its 2 radii `r' and `r2'. If `tag' is positive, set the
-!  tag explicitly; otherwise a new tag is selected automatically. The optional
-!  argument `angle' defines the angular opening (from 0 to 2*Pi). If a vector
-!  `zAxis' of size 3 is provided, use it to define the z-axis. Return the tag
-!  of the torus.
-        function gmshModelOccAddTorus(
-     &      x,
-     &      y,
-     &      z,
-     &      r1,
-     &      r2,
-     &      tag,
-     &      angle,
-     &      zAxis,
-     &      zAxis_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAddTorus")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelOccAddTorus
-            real(c_double), value::x
-            real(c_double), value::y
-            real(c_double), value::z
-            real(c_double), value::r1
-            real(c_double), value::r2
-            integer(c_int), value::tag
-            real(c_double), value::angle
-            real(c_double)::zAxis(*)
-            integer(c_size_t), value :: zAxis_n
-            integer(c_int)::ierr
-          end function gmshModelOccAddTorus
-
-!  Add a volume (if the optional argument `makeSolid' is set) or surfaces in
-!  the OpenCASCADE CAD representation, defined through the open or closed
-!  wires `wireTags'. If `tag' is positive, set the tag explicitly; otherwise a
-!  new tag is selected automatically. The new entities are returned in
-!  `outDimTags'. If the optional argument `makeRuled' is set, the surfaces
-!  created on the boundary are forced to be ruled surfaces. If `maxDegree' is
-!  positive, set the maximal degree of resulting surface. The optional
-!  argument `continuity' allows to specify the continuity of the resulting
-!  shape ("C0", "G1", "C1", "G2", "C2", "C3", "CN"). The optional argument
-!  `parametrization' sets the parametrization type ("ChordLength",
-!  "Centripetal", "IsoParametric"). The optional argument `smoothing'
-!  determines if smoothing is applied.
-        subroutine gmshModelOccAddThruSections(
-     &      wireTags,
-     &      wireTags_n,
-     &      outDimTags,
-     &      outDimTags_n,
-     &      tag,
-     &      makeSolid,
-     &      makeRuled,
-     &      maxDegree,
-     &      continuity,
-     &      parametrization,
-     &      smoothing,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAddThruSections")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::wireTags(*)
-            integer(c_size_t), value :: wireTags_n
-            type(c_ptr), intent(out)::outDimTags
-            integer(c_size_t) :: outDimTags_n
-            integer(c_int), value::tag
-            integer(c_int), value::makeSolid
-            integer(c_int), value::makeRuled
-            integer(c_int), value::maxDegree
-            character(len = 1, kind = c_char)::continuity(*)
-            character(len = 1, kind = c_char)::parametrization(*)
-            integer(c_int), value::smoothing
-            integer(c_int)::ierr
-          end subroutine gmshModelOccAddThruSections
-
-!  Add a hollowed volume in the OpenCASCADE CAD representation, built from an
-!  initial volume `volumeTag' and a set of faces from this volume
-!  `excludeSurfaceTags', which are to be removed. The remaining faces of the
-!  volume become the walls of the hollowed solid, with thickness `offset'. If
-!  `tag' is positive, set the tag explicitly; otherwise a new tag is selected
-!  automatically.
-        subroutine gmshModelOccAddThickSolid(
-     &      volumeTag,
-     &      excludeSurfaceTags,
-     &      excludeSurfaceTags_n,
-     &      offset,
-     &      outDimTags,
-     &      outDimTags_n,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAddThickSolid")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::volumeTag
-            integer(c_int)::excludeSurfaceTags(*)
-            integer(c_size_t), value :: excludeSurfaceTags_n
-            real(c_double), value::offset
-            type(c_ptr), intent(out)::outDimTags
-            integer(c_size_t) :: outDimTags_n
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end subroutine gmshModelOccAddThickSolid
-
-!  Extrude the entities `dimTags' in the OpenCASCADE CAD representation, using
-!  a translation along (`dx', `dy', `dz'). Return 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 (cumulative) height of the different
-!  layers, normalized to 1. If `recombine' is set, recombine the mesh in the
-!  layers.
-        subroutine gmshModelOccExtrude(
-     &      dimTags,
-     &      dimTags_n,
-     &      dx,
-     &      dy,
-     &      dz,
-     &      outDimTags,
-     &      outDimTags_n,
-     &      numElements,
-     &      numElements_n,
-     &      heights,
-     &      heights_n,
-     &      recombine,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccExtrude")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            real(c_double), value::dx
-            real(c_double), value::dy
-            real(c_double), value::dz
-            type(c_ptr), intent(out)::outDimTags
-            integer(c_size_t) :: outDimTags_n
-            integer(c_int)::numElements(*)
-            integer(c_size_t), value :: numElements_n
-            real(c_double)::heights(*)
-            integer(c_size_t), value :: heights_n
-            integer(c_int), value::recombine
-            integer(c_int)::ierr
-          end subroutine gmshModelOccExtrude
-
-!  Extrude the entities `dimTags' in the OpenCASCADE CAD representation, using
-!  a rotation of `angle' radians around the axis of revolution defined by the
-!  point (`x', `y', `z') and the direction (`ax', `ay', `az'). Return 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 (cumulative) height of the
-!  different layers, normalized to 1. When the mesh is extruded the angle
-!  should be strictly smaller than 2*Pi. If `recombine' is set, recombine the
-!  mesh in the layers.
-        subroutine gmshModelOccRevolve(
-     &      dimTags,
-     &      dimTags_n,
-     &      x,
-     &      y,
-     &      z,
-     &      ax,
-     &      ay,
-     &      az,
-     &      angle,
-     &      outDimTags,
-     &      outDimTags_n,
-     &      numElements,
-     &      numElements_n,
-     &      heights,
-     &      heights_n,
-     &      recombine,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccRevolve")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            real(c_double), value::x
-            real(c_double), value::y
-            real(c_double), value::z
-            real(c_double), value::ax
-            real(c_double), value::ay
-            real(c_double), value::az
-            real(c_double), value::angle
-            type(c_ptr), intent(out)::outDimTags
-            integer(c_size_t) :: outDimTags_n
-            integer(c_int)::numElements(*)
-            integer(c_size_t), value :: numElements_n
-            real(c_double)::heights(*)
-            integer(c_size_t), value :: heights_n
-            integer(c_int), value::recombine
-            integer(c_int)::ierr
-          end subroutine gmshModelOccRevolve
-
-!  Add a pipe in the OpenCASCADE CAD representation, by extruding the entities
-!  `dimTags' along the wire `wireTag'. The type of sweep can be specified with
-!  `trihedron' (possible values: "DiscreteTrihedron", "CorrectedFrenet",
-!  "Fixed", "Frenet", "ConstantNormal", "Darboux", "GuideAC", "GuidePlan",
-!  "GuideACWithContact", "GuidePlanWithContact"). If `trihedron' is not
-!  provided, "DiscreteTrihedron" is assumed. Return the pipe in `outDimTags'.
-        subroutine gmshModelOccAddPipe(
-     &      dimTags,
-     &      dimTags_n,
-     &      wireTag,
-     &      outDimTags,
-     &      outDimTags_n,
-     &      trihedron,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAddPipe")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            integer(c_int), value::wireTag
-            type(c_ptr), intent(out)::outDimTags
-            integer(c_size_t) :: outDimTags_n
-            character(len = 1, kind = c_char)::trihedron(*)
-            integer(c_int)::ierr
-          end subroutine gmshModelOccAddPipe
-
-!  Fillet the volumes `volumeTags' on the curves `curveTags' with radii
-!  `radii'. The `radii' vector can either contain a single radius, as many
-!  radii as `curveTags', or twice as many as `curveTags' (in which case
-!  different radii are provided for the begin and end points of the curves).
-!  Return the filleted entities in `outDimTags'. Remove the original volume if
-!  `removeVolume' is set.
-        subroutine gmshModelOccFillet(
-     &      volumeTags,
-     &      volumeTags_n,
-     &      curveTags,
-     &      curveTags_n,
-     &      radii,
-     &      radii_n,
-     &      outDimTags,
-     &      outDimTags_n,
-     &      removeVolume,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccFillet")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::volumeTags(*)
-            integer(c_size_t), value :: volumeTags_n
-            integer(c_int)::curveTags(*)
-            integer(c_size_t), value :: curveTags_n
-            real(c_double)::radii(*)
-            integer(c_size_t), value :: radii_n
-            type(c_ptr), intent(out)::outDimTags
-            integer(c_size_t) :: outDimTags_n
-            integer(c_int), value::removeVolume
-            integer(c_int)::ierr
-          end subroutine gmshModelOccFillet
-
-!  Chamfer the volumes `volumeTags' on the curves `curveTags' with distances
-!  `distances' measured on surfaces `surfaceTags'. The `distances' vector can
-!  either contain a single distance, as many distances as `curveTags' and
-!  `surfaceTags', or twice as many as `curveTags' and `surfaceTags' (in which
-!  case the first in each pair is measured on the corresponding surface in
-!  `surfaceTags', the other on the other adjacent surface). Return the
-!  chamfered entities in `outDimTags'. Remove the original volume if
-!  `removeVolume' is set.
-        subroutine gmshModelOccChamfer(
-     &      volumeTags,
-     &      volumeTags_n,
-     &      curveTags,
-     &      curveTags_n,
-     &      surfaceTags,
-     &      surfaceTags_n,
-     &      distances,
-     &      distances_n,
-     &      outDimTags,
-     &      outDimTags_n,
-     &      removeVolume,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccChamfer")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::volumeTags(*)
-            integer(c_size_t), value :: volumeTags_n
-            integer(c_int)::curveTags(*)
-            integer(c_size_t), value :: curveTags_n
-            integer(c_int)::surfaceTags(*)
-            integer(c_size_t), value :: surfaceTags_n
-            real(c_double)::distances(*)
-            integer(c_size_t), value :: distances_n
-            type(c_ptr), intent(out)::outDimTags
-            integer(c_size_t) :: outDimTags_n
-            integer(c_int), value::removeVolume
-            integer(c_int)::ierr
-          end subroutine gmshModelOccChamfer
-
-!  Compute the boolean union (the fusion) of the entities `objectDimTags' and
-!  `toolDimTags' in the OpenCASCADE CAD representation. Return the resulting
-!  entities in `outDimTags'. If `tag' is positive, try to set the tag
-!  explicitly (only valid if the boolean operation results in a single
-!  entity). Remove the object if `removeObject' is set. Remove the tool if
-!  `removeTool' is set.
-        subroutine gmshModelOccFuse(
-     &      objectDimTags,
-     &      objectDimTags_n,
-     &      toolDimTags,
-     &      toolDimTags_n,
-     &      outDimTags,
-     &      outDimTags_n,
-     &      outDimTagsMap,
-     &      outDimTagsMap_n,
-     &      outDimTagsMap_nn,
-     &      tag,
-     &      removeObject,
-     &      removeTool,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccFuse")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::objectDimTags(*)
-            integer(c_size_t), value :: objectDimTags_n
-            integer(c_int)::toolDimTags(*)
-            integer(c_size_t), value :: toolDimTags_n
-            type(c_ptr), intent(out)::outDimTags
-            integer(c_size_t) :: outDimTags_n
-            type (C_PTR), intent(out)::outDimTagsMap
-            type(c_ptr), intent(out) :: outDimTagsMap_n
-            integer (C_SIZE_T) ::outDimTagsMap_nn
-            integer(c_int), value::tag
-            integer(c_int), value::removeObject
-            integer(c_int), value::removeTool
-            integer(c_int)::ierr
-          end subroutine gmshModelOccFuse
-
-!  Compute the boolean intersection (the common parts) of the entities
-!  `objectDimTags' and `toolDimTags' in the OpenCASCADE CAD representation.
-!  Return the resulting entities in `outDimTags'. If `tag' is positive, try to
-!  set the tag explicitly (only valid if the boolean operation results in a
-!  single entity). Remove the object if `removeObject' is set. Remove the tool
-!  if `removeTool' is set.
-        subroutine gmshModelOccIntersect(
-     &      objectDimTags,
-     &      objectDimTags_n,
-     &      toolDimTags,
-     &      toolDimTags_n,
-     &      outDimTags,
-     &      outDimTags_n,
-     &      outDimTagsMap,
-     &      outDimTagsMap_n,
-     &      outDimTagsMap_nn,
-     &      tag,
-     &      removeObject,
-     &      removeTool,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccIntersect")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::objectDimTags(*)
-            integer(c_size_t), value :: objectDimTags_n
-            integer(c_int)::toolDimTags(*)
-            integer(c_size_t), value :: toolDimTags_n
-            type(c_ptr), intent(out)::outDimTags
-            integer(c_size_t) :: outDimTags_n
-            type (C_PTR), intent(out)::outDimTagsMap
-            type(c_ptr), intent(out) :: outDimTagsMap_n
-            integer (C_SIZE_T) ::outDimTagsMap_nn
-            integer(c_int), value::tag
-            integer(c_int), value::removeObject
-            integer(c_int), value::removeTool
-            integer(c_int)::ierr
-          end subroutine gmshModelOccIntersect
-
-!  Compute the boolean difference between the entities `objectDimTags' and
-!  `toolDimTags' in the OpenCASCADE CAD representation. Return the resulting
-!  entities in `outDimTags'. If `tag' is positive, try to set the tag
-!  explicitly (only valid if the boolean operation results in a single
-!  entity). Remove the object if `removeObject' is set. Remove the tool if
-!  `removeTool' is set.
-        subroutine gmshModelOccCut(
-     &      objectDimTags,
-     &      objectDimTags_n,
-     &      toolDimTags,
-     &      toolDimTags_n,
-     &      outDimTags,
-     &      outDimTags_n,
-     &      outDimTagsMap,
-     &      outDimTagsMap_n,
-     &      outDimTagsMap_nn,
-     &      tag,
-     &      removeObject,
-     &      removeTool,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccCut")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::objectDimTags(*)
-            integer(c_size_t), value :: objectDimTags_n
-            integer(c_int)::toolDimTags(*)
-            integer(c_size_t), value :: toolDimTags_n
-            type(c_ptr), intent(out)::outDimTags
-            integer(c_size_t) :: outDimTags_n
-            type (C_PTR), intent(out)::outDimTagsMap
-            type(c_ptr), intent(out) :: outDimTagsMap_n
-            integer (C_SIZE_T) ::outDimTagsMap_nn
-            integer(c_int), value::tag
-            integer(c_int), value::removeObject
-            integer(c_int), value::removeTool
-            integer(c_int)::ierr
-          end subroutine gmshModelOccCut
-
-!  Compute the boolean fragments (general fuse) resulting from the
-!  intersection of the entities `objectDimTags' and `toolDimTags' in the
-!  OpenCASCADE CAD representation, making all iterfaces conformal. When
-!  applied to entities of different dimensions, the lower dimensional entities
-!  will be automatically embedded in the higher dimensional entities if they
-!  are not on their boundary. Return the resulting entities in `outDimTags'.
-!  If `tag' is positive, try to set the tag explicitly (only valid if the
-!  boolean operation results in a single entity). Remove the object if
-!  `removeObject' is set. Remove the tool if `removeTool' is set.
-        subroutine gmshModelOccFragment(
-     &      objectDimTags,
-     &      objectDimTags_n,
-     &      toolDimTags,
-     &      toolDimTags_n,
-     &      outDimTags,
-     &      outDimTags_n,
-     &      outDimTagsMap,
-     &      outDimTagsMap_n,
-     &      outDimTagsMap_nn,
-     &      tag,
-     &      removeObject,
-     &      removeTool,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccFragment")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::objectDimTags(*)
-            integer(c_size_t), value :: objectDimTags_n
-            integer(c_int)::toolDimTags(*)
-            integer(c_size_t), value :: toolDimTags_n
-            type(c_ptr), intent(out)::outDimTags
-            integer(c_size_t) :: outDimTags_n
-            type (C_PTR), intent(out)::outDimTagsMap
-            type(c_ptr), intent(out) :: outDimTagsMap_n
-            integer (C_SIZE_T) ::outDimTagsMap_nn
-            integer(c_int), value::tag
-            integer(c_int), value::removeObject
-            integer(c_int), value::removeTool
-            integer(c_int)::ierr
-          end subroutine gmshModelOccFragment
-
-!  Translate the entities `dimTags' in the OpenCASCADE CAD representation
-!  along (`dx', `dy', `dz').
-        subroutine gmshModelOccTranslate(
-     &      dimTags,
-     &      dimTags_n,
-     &      dx,
-     &      dy,
-     &      dz,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccTranslate")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            real(c_double), value::dx
-            real(c_double), value::dy
-            real(c_double), value::dz
-            integer(c_int)::ierr
-          end subroutine gmshModelOccTranslate
-
-!  Rotate the entities `dimTags' in the OpenCASCADE CAD representation by
-!  `angle' radians around the axis of revolution defined by the point (`x',
-!  `y', `z') and the direction (`ax', `ay', `az').
-        subroutine gmshModelOccRotate(
-     &      dimTags,
-     &      dimTags_n,
-     &      x,
-     &      y,
-     &      z,
-     &      ax,
-     &      ay,
-     &      az,
-     &      angle,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccRotate")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            real(c_double), value::x
-            real(c_double), value::y
-            real(c_double), value::z
-            real(c_double), value::ax
-            real(c_double), value::ay
-            real(c_double), value::az
-            real(c_double), value::angle
-            integer(c_int)::ierr
-          end subroutine gmshModelOccRotate
-
-!  Scale the entities `dimTags' in the OpenCASCADE CAD representation by
-!  factors `a', `b' and `c' along the three coordinate axes; use (`x', `y',
-!  `z') as the center of the homothetic transformation.
-        subroutine gmshModelOccDilate(
-     &      dimTags,
-     &      dimTags_n,
-     &      x,
-     &      y,
-     &      z,
-     &      a,
-     &      b,
-     &      c,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccDilate")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            real(c_double), value::x
-            real(c_double), value::y
-            real(c_double), value::z
-            real(c_double), value::a
-            real(c_double), value::b
-            real(c_double), value::c
-            integer(c_int)::ierr
-          end subroutine gmshModelOccDilate
-
-!  Mirror the entities `dimTags' in the OpenCASCADE CAD representation, with
-!  respect to the plane of equation `a' * x + `b' * y + `c' * z + `d' = 0.
-        subroutine gmshModelOccMirror(
-     &      dimTags,
-     &      dimTags_n,
-     &      a,
-     &      b,
-     &      c,
-     &      d,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccMirror")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            real(c_double), value::a
-            real(c_double), value::b
-            real(c_double), value::c
-            real(c_double), value::d
-            integer(c_int)::ierr
-          end subroutine gmshModelOccMirror
-
-!  Mirror the entities `dimTags' in the OpenCASCADE CAD representation, with
-!  respect to the plane of equation `a' * x + `b' * y + `c' * z + `d' = 0.
-!  (This is a deprecated synonym for `mirror'.)
-        subroutine gmshModelOccSymmetrize(
-     &      dimTags,
-     &      dimTags_n,
-     &      a,
-     &      b,
-     &      c,
-     &      d,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccSymmetrize")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            real(c_double), value::a
-            real(c_double), value::b
-            real(c_double), value::c
-            real(c_double), value::d
-            integer(c_int)::ierr
-          end subroutine gmshModelOccSymmetrize
-
-!  Apply a general affine transformation matrix `affineTransform' (16 entries
-!  of a 4x4 matrix, by row; only the 12 first can be provided for convenience)
-!  to the entities `dimTags' in the OpenCASCADE CAD representation.
-        subroutine gmshModelOccAffineTransform(
-     &      dimTags,
-     &      dimTags_n,
-     &      affineTransform,
-     &      affineTransform_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccAffineTransform")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            real(c_double)::affineTransform(*)
-            integer(c_size_t), value :: affineTransform_n
-            integer(c_int)::ierr
-          end subroutine gmshModelOccAffineTransform
-
-!  Copy the entities `dimTags' in the OpenCASCADE CAD representation; the new
-!  entities are returned in `outDimTags'.
-        subroutine gmshModelOccCopy(
-     &      dimTags,
-     &      dimTags_n,
-     &      outDimTags,
-     &      outDimTags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccCopy")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            type(c_ptr), intent(out)::outDimTags
-            integer(c_size_t) :: outDimTags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelOccCopy
-
-!  Remove the entities `dimTags' in the OpenCASCADE CAD representation,
-!  provided that they are not on the boundary of higher-dimensional entities.
-!  If `recursive' is true, remove all the entities on their boundaries, down
-!  to dimension 0.
-        subroutine gmshModelOccRemove(
-     &      dimTags,
-     &      dimTags_n,
-     &      recursive,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccRemove")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            integer(c_int), value::recursive
-            integer(c_int)::ierr
-          end subroutine gmshModelOccRemove
-
-!  Remove all duplicate entities in the OpenCASCADE CAD representation
-!  (different entities at the same geometrical location) after intersecting
-!  (using boolean fragments) all highest dimensional entities.
-        subroutine gmshModelOccRemoveAllDuplicates(
-     &      ierr)
-     &    bind(C, name = "gmshModelOccRemoveAllDuplicates")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::ierr
-          end subroutine gmshModelOccRemoveAllDuplicates
-
-!  Apply various healing procedures to the entities `dimTags' (or to all the
-!  entities in the model if `dimTags' is empty) in the OpenCASCADE CAD
-!  representation. Return the healed entities in `outDimTags'.
-        subroutine gmshModelOccHealShapes(
-     &      outDimTags,
-     &      outDimTags_n,
-     &      dimTags,
-     &      dimTags_n,
-     &      tolerance,
-     &      fixDegenerated,
-     &      fixSmallEdges,
-     &      fixSmallFaces,
-     &      sewFaces,
-     &      makeSolids,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccHealShapes")
-          use, intrinsic :: iso_c_binding
-            type(c_ptr), intent(out)::outDimTags
-            integer(c_size_t) :: outDimTags_n
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            real(c_double), value::tolerance
-            integer(c_int), value::fixDegenerated
-            integer(c_int), value::fixSmallEdges
-            integer(c_int), value::fixSmallFaces
-            integer(c_int), value::sewFaces
-            integer(c_int), value::makeSolids
-            integer(c_int)::ierr
-          end subroutine gmshModelOccHealShapes
-
-!  Convert the entities `dimTags' to NURBS.
-        subroutine gmshModelOccConvertToNURBS(
-     &      dimTags,
-     &      dimTags_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccConvertToNURBS")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            integer(c_int)::ierr
-          end subroutine gmshModelOccConvertToNURBS
-
-!  Import BREP, STEP or IGES shapes from the file `fileName' in the
-!  OpenCASCADE CAD representation. The imported entities are returned in
-!  `outDimTags'. If the optional argument `highestDimOnly' is set, only import
-!  the highest dimensional entities in the file. The optional argument
-!  `format' can be used to force the format of the file (currently "brep",
-!  "step" or "iges").
-        subroutine gmshModelOccImportShapes(
-     &      fileName,
-     &      outDimTags,
-     &      outDimTags_n,
-     &      highestDimOnly,
-     &      format,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccImportShapes")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::fileName(*)
-            type(c_ptr), intent(out)::outDimTags
-            integer(c_size_t) :: outDimTags_n
-            integer(c_int), value::highestDimOnly
-            character(len = 1, kind = c_char)::format(*)
-            integer(c_int)::ierr
-          end subroutine gmshModelOccImportShapes
-
-!  Imports an OpenCASCADE `shape' by providing a pointer to a native
-!  OpenCASCADE `TopoDS_Shape' object (passed as a pointer to void). The
-!  imported entities are returned in `outDimTags'. If the optional argument
-!  `highestDimOnly' is set, only import the highest dimensional entities in
-!  `shape'. In Python, this function can be used for integration with
-!  PythonOCC, in which the SwigPyObject pointer of `TopoDS_Shape' must be
-!  passed as an int to `shape', i.e., `shape = int(pythonocc_shape.this)'.
-!  Warning: this function is unsafe, as providing an invalid pointer will lead
-!  to undefined behavior.
-        subroutine gmshModelOccImportShapesNativePointer(
-     &      shape,
-     &      outDimTags,
-     &      outDimTags_n,
-     &      highestDimOnly,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccImportShapesNativePointer")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::shape(*)
-            type(c_ptr), intent(out)::outDimTags
-            integer(c_size_t) :: outDimTags_n
-            integer(c_int), value::highestDimOnly
-            integer(c_int)::ierr
-          end subroutine gmshModelOccImportShapesNativePointer
-
-!  Get all the OpenCASCADE entities. If `dim' is >= 0, return 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.
-        subroutine gmshModelOccGetEntities(
-     &      dimTags,
-     &      dimTags_n,
-     &      dim,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccGetEntities")
-          use, intrinsic :: iso_c_binding
-            type(c_ptr), intent(out)::dimTags
-            integer(c_size_t) :: dimTags_n
-            integer(c_int), value::dim
-            integer(c_int)::ierr
-          end subroutine gmshModelOccGetEntities
-
-!  Get the OpenCASCADE entities in the bounding box defined by the two points
-!  (`xmin', `ymin', `zmin') and (`xmax', `ymax', `zmax'). If `dim' is >= 0,
-!  return only the entities of the specified dimension (e.g. points if `dim'
-!  == 0).
-        subroutine gmshModelOccGetEntitiesInBoundingBox(
-     &      xmin,
-     &      ymin,
-     &      zmin,
-     &      xmax,
-     &      ymax,
-     &      zmax,
-     &      tags,
-     &      tags_n,
-     &      dim,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccGetEntitiesInBoundingBox")
-          use, intrinsic :: iso_c_binding
-            real(c_double), value::xmin
-            real(c_double), value::ymin
-            real(c_double), value::zmin
-            real(c_double), value::xmax
-            real(c_double), value::ymax
-            real(c_double), value::zmax
-            type(c_ptr), intent(out)::tags
-            integer(c_size_t) :: tags_n
-            integer(c_int), value::dim
-            integer(c_int)::ierr
-          end subroutine gmshModelOccGetEntitiesInBoundingBox
-
-!  Get the bounding box (`xmin', `ymin', `zmin'), (`xmax', `ymax', `zmax') of
-!  the OpenCASCADE entity of dimension `dim' and tag `tag'.
-        subroutine gmshModelOccGetBoundingBox(
-     &      dim,
-     &      tag,
-     &      xmin,
-     &      ymin,
-     &      zmin,
-     &      xmax,
-     &      ymax,
-     &      zmax,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccGetBoundingBox")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            real(c_double)::xmin
-            real(c_double)::ymin
-            real(c_double)::zmin
-            real(c_double)::xmax
-            real(c_double)::ymax
-            real(c_double)::zmax
-            integer(c_int)::ierr
-          end subroutine gmshModelOccGetBoundingBox
-
-!  Get the tags `curveLoopTags' of the curve loops making up the surface of
-!  tag `surfaceTag', as well as the tags `curveTags' of the curves making up
-!  each curve loop.
-        subroutine gmshModelOccGetCurveLoops(
-     &      surfaceTag,
-     &      curveLoopTags,
-     &      curveLoopTags_n,
-     &      curveTags,
-     &      curveTags_n,
-     &      curveTags_nn,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccGetCurveLoops")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::surfaceTag
-            type(c_ptr), intent(out)::curveLoopTags
-            integer(c_size_t) :: curveLoopTags_n
-            type(c_ptr), intent(out)::curveTags
-            type(c_ptr), intent(out) :: curveTags_n
-            integer(c_size_t) :: curveTags_nn
-            integer(c_int)::ierr
-          end subroutine gmshModelOccGetCurveLoops
-
-!  Get the tags `surfaceLoopTags' of the surface loops making up the volume of
-!  tag `volumeTag', as well as the tags `surfaceTags' of the surfaces making
-!  up each surface loop.
-        subroutine gmshModelOccGetSurfaceLoops(
-     &      volumeTag,
-     &      surfaceLoopTags,
-     &      surfaceLoopTags_n,
-     &      surfaceTags,
-     &      surfaceTags_n,
-     &      surfaceTags_nn,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccGetSurfaceLoops")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::volumeTag
-            type(c_ptr), intent(out)::surfaceLoopTags
-            integer(c_size_t) :: surfaceLoopTags_n
-            type(c_ptr), intent(out)::surfaceTags
-            type(c_ptr), intent(out) :: surfaceTags_n
-            integer(c_size_t) :: surfaceTags_nn
-            integer(c_int)::ierr
-          end subroutine gmshModelOccGetSurfaceLoops
-
-!  Get the mass of the OpenCASCADE entity of dimension `dim' and tag `tag'.
-        subroutine gmshModelOccGetMass(
-     &      dim,
-     &      tag,
-     &      mass,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccGetMass")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            real(c_double)::mass
-            integer(c_int)::ierr
-          end subroutine gmshModelOccGetMass
-
-!  Get the center of mass of the OpenCASCADE entity of dimension `dim' and tag
-!  `tag'.
-        subroutine gmshModelOccGetCenterOfMass(
-     &      dim,
-     &      tag,
-     &      x,
-     &      y,
-     &      z,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccGetCenterOfMass")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            real(c_double)::x
-            real(c_double)::y
-            real(c_double)::z
-            integer(c_int)::ierr
-          end subroutine gmshModelOccGetCenterOfMass
-
-!  Get the matrix of inertia (by row) of the OpenCASCADE entity of dimension
-!  `dim' and tag `tag'.
-        subroutine gmshModelOccGetMatrixOfInertia(
-     &      dim,
-     &      tag,
-     &      mat,
-     &      mat_n,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccGetMatrixOfInertia")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            type(c_ptr), intent(out)::mat
-            integer(c_size_t) :: mat_n
-            integer(c_int)::ierr
-          end subroutine gmshModelOccGetMatrixOfInertia
-
-!  Get the maximum tag of entities of dimension `dim' in the OpenCASCADE CAD
-!  representation.
-        function gmshModelOccGetMaxTag(
-     &      dim,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccGetMaxTag")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshModelOccGetMaxTag
-            integer(c_int), value::dim
-            integer(c_int)::ierr
-          end function gmshModelOccGetMaxTag
-
-!  Set the maximum tag `maxTag' for entities of dimension `dim' in the
-!  OpenCASCADE CAD representation.
-        subroutine gmshModelOccSetMaxTag(
-     &      dim,
-     &      maxTag,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccSetMaxTag")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::maxTag
-            integer(c_int)::ierr
-          end subroutine gmshModelOccSetMaxTag
-
-!  Synchronize the 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. Without synchronization the entities in the OpenCASCADE CAD
-!  representation are not available to any function outside of the OpenCASCADE
-!  CAD kernel functions.
-        subroutine gmshModelOccSynchronize(
-     &      ierr)
-     &    bind(C, name = "gmshModelOccSynchronize")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::ierr
-          end subroutine gmshModelOccSynchronize
-
-!  Set a mesh size constraint on the entities `dimTags' in the OpenCASCADE CAD
-!  representation. Currently only entities of dimension 0 (points) are
-!  handled.
-        subroutine gmshModelOccMeshSetSize(
-     &      dimTags,
-     &      dimTags_n,
-     &      size,
-     &      ierr)
-     &    bind(C, name = "gmshModelOccMeshSetSize")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::dimTags(*)
-            integer(c_size_t), value :: dimTags_n
-            real(c_double), value::size
-            integer(c_int)::ierr
-          end subroutine gmshModelOccMeshSetSize
-
-!  Add 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. Return the view tag.
-        function gmshViewAdd(
-     &      name,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshViewAdd")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshViewAdd
-            character(len = 1, kind = c_char)::name(*)
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end function gmshViewAdd
-
-!  Remove the view with tag `tag'.
-        subroutine gmshViewRemove(
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshViewRemove")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end subroutine gmshViewRemove
-
-!  Get 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.
-        function gmshViewGetIndex(
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshViewGetIndex")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshViewGetIndex
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end function gmshViewGetIndex
-
-!  Get the tags of all views.
-        subroutine gmshViewGetTags(
-     &      tags,
-     &      tags_n,
-     &      ierr)
-     &    bind(C, name = "gmshViewGetTags")
-          use, intrinsic :: iso_c_binding
-            type(c_ptr), intent(out)::tags
-            integer(c_size_t) :: tags_n
-            integer(c_int)::ierr
-          end subroutine gmshViewGetTags
-
-!  Add 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". `step' specifies the identifier (>= 0) of the data in a
-!  sequence. `tags' gives the tags of the nodes or elements in the mesh to
-!  which the data is associated. `data' is a vector of the same length as
-!  `tags': each entry is the vector of double precision numbers representing
-!  the data associated with the corresponding tag. The optional `time'
-!  argument associate a 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 one to specify data in several sub-sets.
-        subroutine gmshViewAddModelData(
-     &      tag,
-     &      step,
-     &      modelName,
-     &      dataType,
-     &      tags,
-     &      tags_n,
-     &      data,
-     &      data_n,
-     &      data_nn,
-     &      time,
-     &      numComponents,
-     &      partition,
-     &      ierr)
-     &    bind(C, name = "gmshViewAddModelData")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            integer(c_int), value::step
-            character(len = 1, kind = c_char)::modelName(*)
-            character(len = 1, kind = c_char)::dataType(*)
-            integer(c_size_t)::tags(*)
-            integer(c_size_t), value :: tags_n
-            type(c_ptr), intent(out)::data
-            type(c_ptr), intent(out) :: data_n
-            integer(c_size_t) :: data_nn
-            real(c_double), value::time
-            integer(c_int), value::numComponents
-            integer(c_int), value::partition
-            integer(c_int)::ierr
-          end subroutine gmshViewAddModelData
-
-!  Add homogeneous model-based post-processing data to the view with tag
-!  `tag'. The arguments have the same meaning as in `addModelData', except
-!  that `data' is supposed to be homogeneous and is thus flattened in a single
-!  vector. For data types that can lead to different data sizes per tag (like
-!  "ElementNodeData"), the data should be padded.
-        subroutine gmshViewAddHomogeneousModelData(
-     &      tag,
-     &      step,
-     &      modelName,
-     &      dataType,
-     &      tags,
-     &      tags_n,
-     &      data,
-     &      data_n,
-     &      time,
-     &      numComponents,
-     &      partition,
-     &      ierr)
-     &    bind(C, name = "gmshViewAddHomogeneousModelData")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            integer(c_int), value::step
-            character(len = 1, kind = c_char)::modelName(*)
-            character(len = 1, kind = c_char)::dataType(*)
-            integer(c_size_t)::tags(*)
-            integer(c_size_t), value :: tags_n
-            real(c_double)::data(*)
-            integer(c_size_t), value :: data_n
-            real(c_double), value::time
-            integer(c_int), value::numComponents
-            integer(c_int), value::partition
-            integer(c_int)::ierr
-          end subroutine gmshViewAddHomogeneousModelData
-
-!  Get model-based post-processing data from the view with tag `tag' at step
-!  `step'. Return the `data' associated to the nodes or the elements with tags
-!  `tags', as well as the `dataType' and the number of components
-!  `numComponents'.
-        subroutine gmshViewGetModelData(
-     &      tag,
-     &      step,
-     &      dataType,
-     &      tags,
-     &      tags_n,
-     &      data,
-     &      data_n,
-     &      data_nn,
-     &      time,
-     &      numComponents,
-     &      ierr)
-     &    bind(C, name = "gmshViewGetModelData")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            integer(c_int), value::step
-            type(c_ptr)::dataType(*)
-            type(c_ptr), intent(out)::tags
-            integer(c_size_t) :: tags_n
-            type (c_ptr), intent(out)::data
-            type(c_ptr), intent(out) :: data_n
-            integer (c_size_t) :: data_nn
-            real(c_double)::time
-            integer(c_int)::numComponents
-            integer(c_int)::ierr
-          end subroutine gmshViewGetModelData
-
-!  Get homogeneous model-based post-processing data from the view with tag
-!  `tag' at step `step'. The arguments have the same meaning as in
-!  `getModelData', except that `data' is returned flattened in a single
-!  vector, with the appropriate padding if necessary.
-        subroutine gmshViewGetHomogeneousModelData(
-     &      tag,
-     &      step,
-     &      dataType,
-     &      tags,
-     &      tags_n,
-     &      data,
-     &      data_n,
-     &      time,
-     &      numComponents,
-     &      ierr)
-     &    bind(C, name = "gmshViewGetHomogeneousModelData")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            integer(c_int), value::step
-            type(c_ptr)::dataType(*)
-            type(c_ptr), intent(out)::tags
-            integer(c_size_t) :: tags_n
-            type(c_ptr), intent(out)::data
-            integer(c_size_t) :: data_n
-            real(c_double)::time
-            integer(c_int)::numComponents
-            integer(c_int)::ierr
-          end subroutine gmshViewGetHomogeneousModelData
-
-!  Add list-based post-processing data to the view with tag `tag'. List-based
-!  datasets are independent from any model and any mesh. `dataType' identifies
-!  the data by concatenating the field type ("S" for scalar, "V" for vector,
-!  "T" for tensor) and the element type ("P" for point, "L" for line, "T" for
-!  triangle, "S" for tetrahedron, "I" for prism, "H" for hexaHedron, "Y" for
-!  pyramid). For example `dataType' should be "ST" for a scalar field on
-!  triangles. `numEle' gives the number of elements in the data. `data'
-!  contains the data for the `numEle' elements, concatenated, with node
-!  coordinates followed by values per node, repeated for each step: [e1x1,
-!  ..., e1xn, e1y1, ..., e1yn, e1z1, ..., e1zn, e1v1..., e1vN, e2x1, ...].
-        subroutine gmshViewAddListData(
-     &      tag,
-     &      dataType,
-     &      numEle,
-     &      data,
-     &      data_n,
-     &      ierr)
-     &    bind(C, name = "gmshViewAddListData")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            character(len = 1, kind = c_char)::dataType(*)
-            integer(c_int), value::numEle
-            real(c_double)::data(*)
-            integer(c_size_t), value :: data_n
-            integer(c_int)::ierr
-          end subroutine gmshViewAddListData
-
-!  Get list-based post-processing data from the view with tag `tag'. Return
-!  the types `dataTypes', the number of elements `numElements' for each data
-!  type and the `data' for each data type.
-        subroutine gmshViewGetListData(
-     &      tag,
-     &      dataType,
-     &      dataType_n,
-     &      numElements,
-     &      numElements_n,
-     &      data,
-     &      data_n,
-     &      data_nn,
-     &      ierr)
-     &    bind(C, name = "gmshViewGetListData")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            type(c_ptr), intent(out)::dataType
-            integer(c_size_t) :: dataType_n
-            type(c_ptr), intent(out)::numElements
-            integer(c_size_t) :: numElements_n
-            type (c_ptr), intent(out)::data
-            type(c_ptr), intent(out) :: data_n
-            integer (c_size_t) :: data_nn
-            integer(c_int)::ierr
-          end subroutine gmshViewGetListData
-
-!  Add a string to a list-based post-processing view with tag `tag'. If
-!  `coord' contains 3 coordinates the string is positioned in the 3D model
-!  space ("3D string"); if it contains 2 coordinates it is positioned in the
-!  2D graphics viewport ("2D string"). `data' contains one or more (for
-!  multistep views) strings. `style' contains key-value pairs of styling
-!  parameters, concatenated. Available keys are "Font" (possible values:
-!  "Times-Roman", "Times-Bold", "Times-Italic", "Times-BoldItalic",
-!  "Helvetica", "Helvetica-Bold", "Helvetica-Oblique", "Helvetica-
-!  BoldOblique", "Courier", "Courier-Bold", "Courier-Oblique", "Courier-
-!  BoldOblique", "Symbol", "ZapfDingbats", "Screen"), "FontSize" and "Align"
-!  (possible values: "Left" or "BottomLeft", "Center" or "BottomCenter",
-!  "Right" or "BottomRight", "TopLeft", "TopCenter", "TopRight", "CenterLeft",
-!  "CenterCenter", "CenterRight").
-        subroutine gmshViewAddListDataString(
-     &      tag,
-     &      coord,
-     &      coord_n,
-     &      data,
-     &      data_n,
-     &      style,
-     &      style_n,
-     &      ierr)
-     &    bind(C, name = "gmshViewAddListDataString")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            real(c_double)::coord(*)
-            integer(c_size_t), value :: coord_n
-            type(c_ptr)::data(*)
-            integer(c_size_t), value :: data_n
-            type(c_ptr)::style(*)
-            integer(c_size_t), value :: style_n
-            integer(c_int)::ierr
-          end subroutine gmshViewAddListDataString
-
-!  Get list-based post-processing data strings (2D strings if `dim' = 2, 3D
-!  strings if `dim' = 3) from the view with tag `tag'. Return the coordinates
-!  in `coord', the strings in `data' and the styles in `style'.
-        subroutine gmshViewGetListDataStrings(
-     &      tag,
-     &      dim,
-     &      coord,
-     &      coord_n,
-     &      data,
-     &      data_n,
-     &      style,
-     &      style_n,
-     &      ierr)
-     &    bind(C, name = "gmshViewGetListDataStrings")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            integer(c_int), value::dim
-            type(c_ptr), intent(out)::coord
-            integer(c_size_t) :: coord_n
-            type(c_ptr), intent(out)::data
-            integer(c_size_t) :: data_n
-            type(c_ptr), intent(out)::style
-            integer(c_size_t) :: style_n
-            integer(c_int)::ierr
-          end subroutine gmshViewGetListDataStrings
-
-!  Set interpolation matrices for the element family `type' ("Line",
-!  "Triangle", "Quadrangle", "Tetrahedron", "Hexahedron", "Prism", "Pyramid")
-!  in the view `tag'. The approximation of the values over an element is
-!  written as a linear combination of `d' basis functions f_i(u, v, w) =
-!  sum_(j = 0, ..., `d' - 1) `coef'[i][j] u^`exp'[j][0] v^`exp'[j][1]
-!  w^`exp'[j][2], i = 0, ..., `d'-1, with u, v, w the coordinates in the
-!  reference element. The `coef' matrix (of size `d' x `d') and the `exp'
-!  matrix (of size `d' x 3) are stored as vectors, by row. If `dGeo' is
-!  positive, use `coefGeo' and `expGeo' to define the interpolation of the x,
-!  y, z coordinates of the element in terms of the u, v, w coordinates, in
-!  exactly the same way. If `d' < 0, remove the interpolation matrices.
-        subroutine gmshViewSetInterpolationMatrices(
-     &      tag,
-     &      type,
-     &      d,
-     &      coef,
-     &      coef_n,
-     &      exp,
-     &      exp_n,
-     &      dGeo,
-     &      coefGeo,
-     &      coefGeo_n,
-     &      expGeo,
-     &      expGeo_n,
-     &      ierr)
-     &    bind(C, name = "gmshViewSetInterpolationMatrices")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            character(len = 1, kind = c_char)::type(*)
-            integer(c_int), value::d
-            real(c_double)::coef(*)
-            integer(c_size_t), value :: coef_n
-            real(c_double)::exp(*)
-            integer(c_size_t), value :: exp_n
-            integer(c_int), value::dGeo
-            real(c_double)::coefGeo(*)
-            integer(c_size_t), value :: coefGeo_n
-            real(c_double)::expGeo(*)
-            integer(c_size_t), value :: expGeo_n
-            integer(c_int)::ierr
-          end subroutine gmshViewSetInterpolationMatrices
-
-!  Add a post-processing view as an `alias' of the reference view with tag
-!  `refTag'. If `copyOptions' is set, copy the options of the reference view.
-!  If `tag' is positive use it (and remove the view with that tag if it
-!  already exists), otherwise associate a new tag. Return the view tag.
-        function gmshViewAddAlias(
-     &      refTag,
-     &      copyOptions,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshViewAddAlias")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshViewAddAlias
-            integer(c_int), value::refTag
-            integer(c_int), value::copyOptions
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end function gmshViewAddAlias
-
-!  Combine elements (if `what' == "elements") or steps (if `what' == "steps")
-!  of all views (`how' == "all"), all visible views (`how' == "visible") or
-!  all views having the same name (`how' == "name"). Remove original views if
-!  `remove' is set.
-        subroutine gmshViewCombine(
-     &      what,
-     &      how,
-     &      remove,
-     &      copyOptions,
-     &      ierr)
-     &    bind(C, name = "gmshViewCombine")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::what(*)
-            character(len = 1, kind = c_char)::how(*)
-            integer(c_int), value::remove
-            integer(c_int), value::copyOptions
-            integer(c_int)::ierr
-          end subroutine gmshViewCombine
-
-!  Probe the view `tag' for its `value' at point (`x', `y', `z'). If no match
-!  is found, `value' is returned empty. Return only the value at step `step'
-!  is `step' is positive. Return only values with `numComp' if `numComp' is
-!  positive. Return the gradient of the `value' if `gradient' is set. If
-!  `distanceMax' is zero, only return a result if an exact match inside an
-!  element in the view is found; if `distanceMax' is positive and an exact
-!  match is not found, return the value at the closest node if it is closer
-!  than `distanceMax'; if `distanceMax' is negative and an exact match is not
-!  found, always return the value at the closest node. The distance to the
-!  match is returned in `distance'. Return the result from the element
-!  described by its coordinates if `xElementCoord', `yElementCoord' and
-!  `zElementCoord' are provided. If `dim' is >= 0, return only matches from
-!  elements of the specified dimension.
-        subroutine gmshViewProbe(
-     &      tag,
-     &      x,
-     &      y,
-     &      z,
-     &      value,
-     &      value_n,
-     &      distance,
-     &      step,
-     &      numComp,
-     &      gradient,
-     &      distanceMax,
-     &      xElemCoord,
-     &      xElemCoord_n,
-     &      yElemCoord,
-     &      yElemCoord_n,
-     &      zElemCoord,
-     &      zElemCoord_n,
-     &      dim,
-     &      ierr)
-     &    bind(C, name = "gmshViewProbe")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            real(c_double), value::x
-            real(c_double), value::y
-            real(c_double), value::z
-            type(c_ptr), intent(out)::value
-            integer(c_size_t) :: value_n
-            real(c_double)::distance
-            integer(c_int), value::step
-            integer(c_int), value::numComp
-            integer(c_int), value::gradient
-            real(c_double), value::distanceMax
-            real(c_double)::xElemCoord(*)
-            integer(c_size_t), value :: xElemCoord_n
-            real(c_double)::yElemCoord(*)
-            integer(c_size_t), value :: yElemCoord_n
-            real(c_double)::zElemCoord(*)
-            integer(c_size_t), value :: zElemCoord_n
-            integer(c_int), value::dim
-            integer(c_int)::ierr
-          end subroutine gmshViewProbe
-
-!  Write the view to a file `fileName'. The export format is determined by the
-!  file extension. Append to the file if `append' is set.
-        subroutine gmshViewWrite(
-     &      tag,
-     &      fileName,
-     &      append,
-     &      ierr)
-     &    bind(C, name = "gmshViewWrite")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            character(len = 1, kind = c_char)::fileName(*)
-            integer(c_int), value::append
-            integer(c_int)::ierr
-          end subroutine gmshViewWrite
-
-!  Set the global visibility of the view `tag' per window to `value', where
-!  `windowIndex' identifies the window in the window list.
-        subroutine gmshViewSetVisibilityPerWindow(
-     &      tag,
-     &      value,
-     &      windowIndex,
-     &      ierr)
-     &    bind(C, name = "gmshViewSetVisibilityPerWindow")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            integer(c_int), value::value
-            integer(c_int), value::windowIndex
-            integer(c_int)::ierr
-          end subroutine gmshViewSetVisibilityPerWindow
-
-!  Set the numerical option `name' to value `value' for the view with tag
-!  `tag'.
-        subroutine gmshViewOptionSetNumber(
-     &      tag,
-     &      name,
-     &      value,
-     &      ierr)
-     &    bind(C, name = "gmshViewOptionSetNumber")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            character(len = 1, kind = c_char)::name(*)
-            real(c_double), value::value
-            integer(c_int)::ierr
-          end subroutine gmshViewOptionSetNumber
-
-!  Get the `value' of the numerical option `name' for the view with tag `tag'.
-        subroutine gmshViewOptionGetNumber(
-     &      tag,
-     &      name,
-     &      value,
-     &      ierr)
-     &    bind(C, name = "gmshViewOptionGetNumber")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            character(len = 1, kind = c_char)::name(*)
-            real(c_double)::value
-            integer(c_int)::ierr
-          end subroutine gmshViewOptionGetNumber
-
-!  Set the string option `name' to value `value' for the view with tag `tag'.
-        subroutine gmshViewOptionSetString(
-     &      tag,
-     &      name,
-     &      value,
-     &      ierr)
-     &    bind(C, name = "gmshViewOptionSetString")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            character(len = 1, kind = c_char)::name(*)
-            character(len = 1, kind = c_char)::value(*)
-            integer(c_int)::ierr
-          end subroutine gmshViewOptionSetString
-
-!  Get the `value' of the string option `name' for the view with tag `tag'.
-        subroutine gmshViewOptionGetString(
-     &      tag,
-     &      name,
-     &      value,
-     &      ierr)
-     &    bind(C, name = "gmshViewOptionGetString")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            character(len = 1, kind = c_char)::name(*)
-            type(c_ptr)::value(*)
-            integer(c_int)::ierr
-          end subroutine gmshViewOptionGetString
-
-!  Set the color option `name' to the RGBA value (`r', `g', `b', `a') for the
-!  view with tag `tag', where where `r', `g', `b' and `a' should be integers
-!  between 0 and 255.
-        subroutine gmshViewOptionSetColor(
-     &      tag,
-     &      name,
-     &      r,
-     &      g,
-     &      b,
-     &      a,
-     &      ierr)
-     &    bind(C, name = "gmshViewOptionSetColor")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            character(len = 1, kind = c_char)::name(*)
-            integer(c_int), value::r
-            integer(c_int), value::g
-            integer(c_int), value::b
-            integer(c_int), value::a
-            integer(c_int)::ierr
-          end subroutine gmshViewOptionSetColor
-
-!  Get the `r', `g', `b', `a' value of the color option `name' for the view
-!  with tag `tag'.
-        subroutine gmshViewOptionGetColor(
-     &      tag,
-     &      name,
-     &      r,
-     &      g,
-     &      b,
-     &      a,
-     &      ierr)
-     &    bind(C, name = "gmshViewOptionGetColor")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::tag
-            character(len = 1, kind = c_char)::name(*)
-            integer(c_int)::r
-            integer(c_int)::g
-            integer(c_int)::b
-            integer(c_int)::a
-            integer(c_int)::ierr
-          end subroutine gmshViewOptionGetColor
-
-!  Copy the options from the view with tag `refTag' to the view with tag
-!  `tag'.
-        subroutine gmshViewOptionCopy(
-     &      refTag,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshViewOptionCopy")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::refTag
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end subroutine gmshViewOptionCopy
-
-!  Set the numerical option `option' to the value `value' for plugin `name'.
-        subroutine gmshPluginSetNumber(
-     &      name,
-     &      option,
-     &      value,
-     &      ierr)
-     &    bind(C, name = "gmshPluginSetNumber")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::name(*)
-            character(len = 1, kind = c_char)::option(*)
-            real(c_double), value::value
-            integer(c_int)::ierr
-          end subroutine gmshPluginSetNumber
-
-!  Set the string option `option' to the value `value' for plugin `name'.
-        subroutine gmshPluginSetString(
-     &      name,
-     &      option,
-     &      value,
-     &      ierr)
-     &    bind(C, name = "gmshPluginSetString")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::name(*)
-            character(len = 1, kind = c_char)::option(*)
-            character(len = 1, kind = c_char)::value(*)
-            integer(c_int)::ierr
-          end subroutine gmshPluginSetString
-
-!  Run the plugin `name'. Return the tag of the created view (if any).
-        function gmshPluginRun(
-     &      name,
-     &      ierr)
-     &    bind(C, name = "gmshPluginRun")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshPluginRun
-            character(len = 1, kind = c_char)::name(*)
-            integer(c_int)::ierr
-          end function gmshPluginRun
-
-!  Draw all the OpenGL scenes.
-        subroutine gmshGraphicsDraw(
-     &      ierr)
-     &    bind(C, name = "gmshGraphicsDraw")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::ierr
-          end subroutine gmshGraphicsDraw
-
-!  Create the FLTK graphical user interface. Can only be called in the main
-!  thread.
-        subroutine gmshFltkInitialize(
-     &      ierr)
-     &    bind(C, name = "gmshFltkInitialize")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::ierr
-          end subroutine gmshFltkInitialize
-
-!  Close the FLTK graphical user interface. Can only be called in the main
-!  thread.
-        subroutine gmshFltkFinalize(
-     &      ierr)
-     &    bind(C, name = "gmshFltkFinalize")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::ierr
-          end subroutine gmshFltkFinalize
-
-!  Wait at most `time' seconds for user interface events and return. If `time'
-!  < 0, wait indefinitely. First automatically create the user interface if it
-!  has not yet been initialized. Can only be called in the main thread.
-        subroutine gmshFltkWait(
-     &      time,
-     &      ierr)
-     &    bind(C, name = "gmshFltkWait")
-          use, intrinsic :: iso_c_binding
-            real(c_double), value::time
-            integer(c_int)::ierr
-          end subroutine gmshFltkWait
-
-!  Update the user interface (potentially creating new widgets and windows).
-!  First automatically create the user interface if it has not yet been
-!  initialized. Can only be called in the main thread: use `awake("update")'
-!  to trigger an update of the user interface from another thread.
-        subroutine gmshFltkUpdate(
-     &      ierr)
-     &    bind(C, name = "gmshFltkUpdate")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::ierr
-          end subroutine gmshFltkUpdate
-
-!  Awake the main user interface thread and process pending events, and
-!  optionally perform an action (currently the only `action' allowed is
-!  "update").
-        subroutine gmshFltkAwake(
-     &      action,
-     &      ierr)
-     &    bind(C, name = "gmshFltkAwake")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::action(*)
-            integer(c_int)::ierr
-          end subroutine gmshFltkAwake
-
-!  Block the current thread until it can safely modify the user interface.
-        subroutine gmshFltkLock(
-     &      ierr)
-     &    bind(C, name = "gmshFltkLock")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::ierr
-          end subroutine gmshFltkLock
-
-!  Release the lock that was set using lock.
-        subroutine gmshFltkUnlock(
-     &      ierr)
-     &    bind(C, name = "gmshFltkUnlock")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::ierr
-          end subroutine gmshFltkUnlock
-
-!  Run the event loop of the graphical user interface, i.e. repeatedly call
-!  `wait()'. First automatically create the user interface if it has not yet
-!  been initialized. Can only be called in the main thread.
-        subroutine gmshFltkRun(
-     &      ierr)
-     &    bind(C, name = "gmshFltkRun")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::ierr
-          end subroutine gmshFltkRun
-
-!  Check if the user interface is available (e.g. to detect if it has been
-!  closed).
-        function gmshFltkIsAvailable(
-     &      ierr)
-     &    bind(C, name = "gmshFltkIsAvailable")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshFltkIsAvailable
-            integer(c_int)::ierr
-          end function gmshFltkIsAvailable
-
-!  Select entities in the user interface. If `dim' is >= 0, return only the
-!  entities of the specified dimension (e.g. points if `dim' == 0).
-        function gmshFltkSelectEntities(
-     &      dimTags,
-     &      dimTags_n,
-     &      dim,
-     &      ierr)
-     &    bind(C, name = "gmshFltkSelectEntities")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshFltkSelectEntities
-            type(c_ptr), intent(out)::dimTags
-            integer(c_size_t) :: dimTags_n
-            integer(c_int), value::dim
-            integer(c_int)::ierr
-          end function gmshFltkSelectEntities
-
-!  Select elements in the user interface.
-        function gmshFltkSelectElements(
-     &      elementTags,
-     &      elementTags_n,
-     &      ierr)
-     &    bind(C, name = "gmshFltkSelectElements")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshFltkSelectElements
-            type(c_ptr), intent(out)::elementTags
-            integer(c_size_t) :: elementTags_n
-            integer(c_int)::ierr
-          end function gmshFltkSelectElements
-
-!  Select views in the user interface.
-        function gmshFltkSelectViews(
-     &      viewTags,
-     &      viewTags_n,
-     &      ierr)
-     &    bind(C, name = "gmshFltkSelectViews")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshFltkSelectViews
-            type(c_ptr), intent(out)::viewTags
-            integer(c_size_t) :: viewTags_n
-            integer(c_int)::ierr
-          end function gmshFltkSelectViews
-
-!  Split the current window horizontally (if `how' = "h") or vertically (if
-!  `how' = "v"), using ratio `ratio'. If `how' = "u", restore a single window.
-        subroutine gmshFltkSplitCurrentWindow(
-     &      how,
-     &      ratio,
-     &      ierr)
-     &    bind(C, name = "gmshFltkSplitCurrentWindow")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::how(*)
-            real(c_double), value::ratio
-            integer(c_int)::ierr
-          end subroutine gmshFltkSplitCurrentWindow
-
-!  Set the current window by speficying its index (starting at 0) in the list
-!  of all windows. When new windows are created by splits, new windows are
-!  appended at the end of the list.
-        subroutine gmshFltkSetCurrentWindow(
-     &      windowIndex,
-     &      ierr)
-     &    bind(C, name = "gmshFltkSetCurrentWindow")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::windowIndex
-            integer(c_int)::ierr
-          end subroutine gmshFltkSetCurrentWindow
-
-!  Set a status message in the current window. If `graphics' is set, display
-!  the message inside the graphic window instead of the status bar.
-        subroutine gmshFltkSetStatusMessage(
-     &      message,
-     &      graphics,
-     &      ierr)
-     &    bind(C, name = "gmshFltkSetStatusMessage")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::message(*)
-            integer(c_int), value::graphics
-            integer(c_int)::ierr
-          end subroutine gmshFltkSetStatusMessage
-
-!  Show context window for the entity of dimension `dim' and tag `tag'.
-        subroutine gmshFltkShowContextWindow(
-     &      dim,
-     &      tag,
-     &      ierr)
-     &    bind(C, name = "gmshFltkShowContextWindow")
-          use, intrinsic :: iso_c_binding
-            integer(c_int), value::dim
-            integer(c_int), value::tag
-            integer(c_int)::ierr
-          end subroutine gmshFltkShowContextWindow
-
-!  Open the `name' item in the menu tree.
-        subroutine gmshFltkOpenTreeItem(
-     &      name,
-     &      ierr)
-     &    bind(C, name = "gmshFltkOpenTreeItem")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::name(*)
-            integer(c_int)::ierr
-          end subroutine gmshFltkOpenTreeItem
-
-!  Close the `name' item in the menu tree.
-        subroutine gmshFltkCloseTreeItem(
-     &      name,
-     &      ierr)
-     &    bind(C, name = "gmshFltkCloseTreeItem")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::name(*)
-            integer(c_int)::ierr
-          end subroutine gmshFltkCloseTreeItem
-
-!  Get the names of the variables in the Gmsh parser matching the `search'
-!  regular expression. If `search' is empty, return all the names.
-        subroutine gmshParserGetNames(
-     &      names,
-     &      names_n,
-     &      search,
-     &      ierr)
-     &    bind(C, name = "gmshParserGetNames")
-          use, intrinsic :: iso_c_binding
-            type(c_ptr), intent(out)::names
-            integer(c_size_t) :: names_n
-            character(len = 1, kind = c_char)::search(*)
-            integer(c_int)::ierr
-          end subroutine gmshParserGetNames
-
-!  Set the value of the number variable `name' in the Gmsh parser. Create the
-!  variable if it does not exist; update the value if the variable exists.
-        subroutine gmshParserSetNumber(
-     &      name,
-     &      value,
-     &      value_n,
-     &      ierr)
-     &    bind(C, name = "gmshParserSetNumber")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::name(*)
-            real(c_double)::value(*)
-            integer(c_size_t), value :: value_n
-            integer(c_int)::ierr
-          end subroutine gmshParserSetNumber
-
-!  Set the value of the string variable `name' in the Gmsh parser. Create the
-!  variable if it does not exist; update the value if the variable exists.
-        subroutine gmshParserSetString(
-     &      name,
-     &      value,
-     &      value_n,
-     &      ierr)
-     &    bind(C, name = "gmshParserSetString")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::name(*)
-            type(c_ptr)::value(*)
-            integer(c_size_t), value :: value_n
-            integer(c_int)::ierr
-          end subroutine gmshParserSetString
-
-!  Get the value of the number variable `name' from the Gmsh parser. Return an
-!  empty vector if the variable does not exist.
-        subroutine gmshParserGetNumber(
-     &      name,
-     &      value,
-     &      value_n,
-     &      ierr)
-     &    bind(C, name = "gmshParserGetNumber")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::name(*)
-            type(c_ptr), intent(out)::value
-            integer(c_size_t) :: value_n
-            integer(c_int)::ierr
-          end subroutine gmshParserGetNumber
-
-!  Get the value of the string variable `name' from the Gmsh parser. Return an
-!  empty vector if the variable does not exist.
-        subroutine gmshParserGetString(
-     &      name,
-     &      value,
-     &      value_n,
-     &      ierr)
-     &    bind(C, name = "gmshParserGetString")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::name(*)
-            type(c_ptr), intent(out)::value
-            integer(c_size_t) :: value_n
-            integer(c_int)::ierr
-          end subroutine gmshParserGetString
-
-!  Clear all the Gmsh parser variables, or remove a single variable if `name'
-!  is given.
-        subroutine gmshParserClear(
-     &      name,
-     &      ierr)
-     &    bind(C, name = "gmshParserClear")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::name(*)
-            integer(c_int)::ierr
-          end subroutine gmshParserClear
-
-!  Parse the file `fileName' with the Gmsh parser.
-        subroutine gmshParserParse(
-     &      fileName,
-     &      ierr)
-     &    bind(C, name = "gmshParserParse")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::fileName(*)
-            integer(c_int)::ierr
-          end subroutine gmshParserParse
-
-!  Set one or more parameters in the ONELAB database, encoded in `format'.
-        subroutine gmshOnelabSet(
-     &      data,
-     &      format,
-     &      ierr)
-     &    bind(C, name = "gmshOnelabSet")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::data(*)
-            character(len = 1, kind = c_char)::format(*)
-            integer(c_int)::ierr
-          end subroutine gmshOnelabSet
-
-!  Get all the parameters (or a single one if `name' is specified) from the
-!  ONELAB database, encoded in `format'.
-        subroutine gmshOnelabGet(
-     &      data,
-     &      name,
-     &      format,
-     &      ierr)
-     &    bind(C, name = "gmshOnelabGet")
-          use, intrinsic :: iso_c_binding
-            type(c_ptr)::data(*)
-            character(len = 1, kind = c_char)::name(*)
-            character(len = 1, kind = c_char)::format(*)
-            integer(c_int)::ierr
-          end subroutine gmshOnelabGet
-
-!  Get the names of the parameters in the ONELAB database matching the
-!  `search' regular expression. If `search' is empty, return all the names.
-        subroutine gmshOnelabGetNames(
-     &      names,
-     &      names_n,
-     &      search,
-     &      ierr)
-     &    bind(C, name = "gmshOnelabGetNames")
-          use, intrinsic :: iso_c_binding
-            type(c_ptr), intent(out)::names
-            integer(c_size_t) :: names_n
-            character(len = 1, kind = c_char)::search(*)
-            integer(c_int)::ierr
-          end subroutine gmshOnelabGetNames
-
-!  Set the value of the number parameter `name' in the ONELAB database. Create
-!  the parameter if it does not exist; update the value if the parameter
-!  exists.
-        subroutine gmshOnelabSetNumber(
-     &      name,
-     &      value,
-     &      value_n,
-     &      ierr)
-     &    bind(C, name = "gmshOnelabSetNumber")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::name(*)
-            real(c_double)::value(*)
-            integer(c_size_t), value :: value_n
-            integer(c_int)::ierr
-          end subroutine gmshOnelabSetNumber
-
-!  Set the value of the string parameter `name' in the ONELAB database. Create
-!  the parameter if it does not exist; update the value if the parameter
-!  exists.
-        subroutine gmshOnelabSetString(
-     &      name,
-     &      value,
-     &      value_n,
-     &      ierr)
-     &    bind(C, name = "gmshOnelabSetString")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::name(*)
-            type(c_ptr)::value(*)
-            integer(c_size_t), value :: value_n
-            integer(c_int)::ierr
-          end subroutine gmshOnelabSetString
-
-!  Get the value of the number parameter `name' from the ONELAB database.
-!  Return an empty vector if the parameter does not exist.
-        subroutine gmshOnelabGetNumber(
-     &      name,
-     &      value,
-     &      value_n,
-     &      ierr)
-     &    bind(C, name = "gmshOnelabGetNumber")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::name(*)
-            type(c_ptr), intent(out)::value
-            integer(c_size_t) :: value_n
-            integer(c_int)::ierr
-          end subroutine gmshOnelabGetNumber
-
-!  Get the value of the string parameter `name' from the ONELAB database.
-!  Return an empty vector if the parameter does not exist.
-        subroutine gmshOnelabGetString(
-     &      name,
-     &      value,
-     &      value_n,
-     &      ierr)
-     &    bind(C, name = "gmshOnelabGetString")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::name(*)
-            type(c_ptr), intent(out)::value
-            integer(c_size_t) :: value_n
-            integer(c_int)::ierr
-          end subroutine gmshOnelabGetString
-
-!  Check if any parameters in the ONELAB database used by the client `name'
-!  have been changed.
-        function gmshOnelabGetChanged(
-     &      name,
-     &      ierr)
-     &    bind(C, name = "gmshOnelabGetChanged")
-          use, intrinsic :: iso_c_binding
-          integer(c_int)::gmshOnelabGetChanged
-            character(len = 1, kind = c_char)::name(*)
-            integer(c_int)::ierr
-          end function gmshOnelabGetChanged
-
-!  Set the changed flag to value `value' for all the parameters in the ONELAB
-!  database used by the client `name'.
-        subroutine gmshOnelabSetChanged(
-     &      name,
-     &      value,
-     &      ierr)
-     &    bind(C, name = "gmshOnelabSetChanged")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::name(*)
-            integer(c_int), value::value
-            integer(c_int)::ierr
-          end subroutine gmshOnelabSetChanged
-
-!  Clear the ONELAB database, or remove a single parameter if `name' is given.
-        subroutine gmshOnelabClear(
-     &      name,
-     &      ierr)
-     &    bind(C, name = "gmshOnelabClear")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::name(*)
-            integer(c_int)::ierr
-          end subroutine gmshOnelabClear
-
-!  Run a ONELAB client. If `name' is provided, create a new ONELAB client with
-!  name `name' and executes `command'. If not, try to run a client that might
-!  be linked to the processed input files.
-        subroutine gmshOnelabRun(
-     &      name,
-     &      command,
-     &      ierr)
-     &    bind(C, name = "gmshOnelabRun")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::name(*)
-            character(len = 1, kind = c_char)::command(*)
-            integer(c_int)::ierr
-          end subroutine gmshOnelabRun
-
-!  Write a `message'. `level' can be "info", "warning" or "error".
-        subroutine gmshLoggerWrite(
-     &      message,
-     &      level,
-     &      ierr)
-     &    bind(C, name = "gmshLoggerWrite")
-          use, intrinsic :: iso_c_binding
-            character(len = 1, kind = c_char)::message(*)
-            character(len = 1, kind = c_char)::level(*)
-            integer(c_int)::ierr
-          end subroutine gmshLoggerWrite
-
-!  Start logging messages.
-        subroutine gmshLoggerStart(
-     &      ierr)
-     &    bind(C, name = "gmshLoggerStart")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::ierr
-          end subroutine gmshLoggerStart
-
-!  Get logged messages.
-        subroutine gmshLoggerGet(
-     &      log,
-     &      log_n,
-     &      ierr)
-     &    bind(C, name = "gmshLoggerGet")
-          use, intrinsic :: iso_c_binding
-            type(c_ptr), intent(out)::log
-            integer(c_size_t) :: log_n
-            integer(c_int)::ierr
-          end subroutine gmshLoggerGet
-
-!  Stop logging messages.
-        subroutine gmshLoggerStop(
-     &      ierr)
-     &    bind(C, name = "gmshLoggerStop")
-          use, intrinsic :: iso_c_binding
-            integer(c_int)::ierr
-          end subroutine gmshLoggerStop
-
-!  Return wall clock time.
-        function gmshLoggerGetWallTime(
-     &      ierr)
-     &    bind(C, name = "gmshLoggerGetWallTime")
-          use, intrinsic :: iso_c_binding
-          real(c_double)::gmshLoggerGetWallTime
-            integer(c_int)::ierr
-          end function gmshLoggerGetWallTime
-
-!  Return CPU time.
-        function gmshLoggerGetCpuTime(
-     &      ierr)
-     &    bind(C, name = "gmshLoggerGetCpuTime")
-          use, intrinsic :: iso_c_binding
-          real(c_double)::gmshLoggerGetCpuTime
-            integer(c_int)::ierr
-          end function gmshLoggerGetCpuTime
-
-!  Return last error message, if any.
-        subroutine gmshLoggerGetLastError(
-     &      error,
-     &      ierr)
-     &    bind(C, name = "gmshLoggerGetLastError")
-          use, intrinsic :: iso_c_binding
-            type(c_ptr)::error(*)
-            integer(c_int)::ierr
-          end subroutine gmshLoggerGetLastError
-
-        end interface
-      end module gmsh_fortran
-
-!DEC$ ENDIF
diff --git a/doc/SDK.txt b/doc/SDK.txt
index 23d012b3c6cbde05c34c9616da9717caae47e977..095a7be694ca0885044155dca19c6b7c66d3cf2f 100644
--- a/doc/SDK.txt
+++ b/doc/SDK.txt
@@ -20,12 +20,14 @@ SDK layout:
   * include/gmsh.h: C++ API header
   * include/gmshc.h: C API header
   * include/gmsh.h_cwrap: C++ wrapper of the C API (see the `Notes' below)
+  * include/gmsh.f90: Fortran module
   * bin/gmsh: gmsh executable (linked with the shared Gmsh library)
   * share/doc/gmsh/tutorials/c++: C++ API tutorials
   * share/doc/gmsh/tutorials/c: C API tutorials
   * share/doc/gmsh/tutorials/python: Python API tutorials
   * share/doc/gmsh/tutorials/julia: Julia API tutorials
-  * share/doc/gmsh/examples/api: Other API examples in C++, C, Python and Julia
+  * share/doc/gmsh/tutorials/fortran: Fortran API tutorials
+  * share/doc/gmsh/examples/api: Other API examples
 
 Notes:
 
diff --git a/doc/texinfo/gmsh.texi b/doc/texinfo/gmsh.texi
index 38208b67b6077cbb1b4c7d0b5b2303aeba1b36b2..a76e21214ccf0634fb1a2a85c3138b01ec553b30 100644
--- a/doc/texinfo/gmsh.texi
+++ b/doc/texinfo/gmsh.texi
@@ -231,8 +231,9 @@ instructions are prescribed either interactively using the graphical
 user interface (GUI) or in text files using Gmsh's own scripting
 language.  Interactive actions generate language bits in the input
 files, and vice versa. A programming API is also available, for
-integrating Gmsh in your own C++, C, Python or Julia code: see @ref{Gmsh
-API}. A brief description of the four modules is given hereafter.
+integrating Gmsh in your own C++, C, Python, Julia or Fortran code: see
+@ref{Gmsh API}. A brief description of the four modules is given
+hereafter.
 
 @menu
 * Geometry::
@@ -394,11 +395,12 @@ built-in scripting language, thanks to user-defined macros, loops,
 conditionals and includes (see @ref{User-defined macros}, @ref{Loops and
 conditionals}, and @ref{General commands}). For more advanced
 geometries, using the Gmsh API (@pxref{Gmsh API}) in the language of
-your choice (C++, C, Python or Julia) brings even greater flexibility,
-the only downside being that you need to either compile your code (for
-C++ and C) or to configure and install an interpreter (Python or Julia)
-in addition to Gmsh. A binary Software Development Kit (SDK) is
-distributed on the Gmsh web site to make the process easier;
+your choice (C++, C, Python, Julia or Fortran) brings even greater
+flexibility, the only downside being that you need to either compile
+your code (for C++, C and Fortran) or to configure and install an
+interpreter (Python or Julia) in addition to Gmsh. A binary Software
+Development Kit (SDK) is distributed on the Gmsh web site to make the
+process easier;
 @item
 parametrize these geometries. Gmsh's scripting language or the Gmsh API
 enable all commands and command arguments to depend on previous
@@ -544,8 +546,8 @@ built: check the `File->Export' menu for a list of available formats.
 
 Finally, to use Gmsh at the third level (i.e., to link the Gmsh library
 with your own code), you will need to learn the Gmsh Application
-Programming Interface (API). This API is available in C++, C, Python and
-Julia, and is fully documented in @ref{Gmsh API}.
+Programming Interface (API). This API is available in C++, C, Python,
+Julia and Fortran, and is fully documented in @ref{Gmsh API}.
 
 @c -------------------------------------------------------------------------
 @c Syntactic rules used in the manual
@@ -2900,7 +2902,7 @@ example is available in @ref{t10}.
 All the aforementioned methods can be used simultaneously, in which case
 the smallest element size is selected at any given point.  Using the
 Gmsh API, the resulting value can be further modified using a C++, C,
-Python or Julia mesh size callback function provided via
+Python, Julia or Fortran mesh size callback function provided via
 @code{gmsh/model/mesh/setSizeCallback} (@pxref{Namespace
 gmsh/model/mesh}). In addition, boundary mesh sizes are interpolated
 inside surfaces and/or volumes depending on the value of
@@ -3380,13 +3382,13 @@ Solvers and other external codes can be driven by Gmsh through the
 ONELAB interface (see @url{http://www.onelab.info}), which allows to
 have them share parameters and modeling information.
 
-Using the Gmsh API, you can directly embed Gmsh in your C++, C, Python
-or Julia solver, use ONELAB for interactive parameter definition and
-modification, and to create post-processing data on the fly. See
+Using the Gmsh API, you can directly embed Gmsh in your C++, C, Python,
+Julia or Fotran solver, use ONELAB for interactive parameter definition
+and modification, and to create post-processing data on the fly. See
 @url{@value{GITLAB-PREFIX}/examples/api/prepro.py,prepro.py},
 @url{@value{GITLAB-PREFIX}/examples/api/custom_gui.py,custom_gui.py} and
-@url{@value{GITLAB-PREFIX}/examples/api/custom_gui.cpp,custom_gui.cpp} for
-examples.
+@url{@value{GITLAB-PREFIX}/examples/api/custom_gui.cpp,custom_gui.cpp}
+for examples.
 
 If you prefer to keep codes separate, you can also communicate with Gmsh
 through a socket by providing the solver name (@code{Solver.Name0},
@@ -5219,8 +5221,8 @@ are only available via the API.
 To learn how to run Gmsh on your computer, see @ref{Running Gmsh on your
 system}. Screencasts that show how to use the GUI are available on
 @uref{https://gmsh.info/screencasts/}. To learn how to run the C++, C,
-Python and Julia API examples, see the respective subdirectories in
-@url{@value{GITLAB-PREFIX}/tutorials,tutorials}.
+Python, Julia and Fortran API examples, see the respective
+subdirectories in @url{@value{GITLAB-PREFIX}/tutorials,tutorials}.
 
 @menu
 * t1::  Geometry basics, elementary entities, physical groups
@@ -5267,9 +5269,11 @@ available in C++
 C
 (@url{@value{GITLAB-PREFIX}/tutorials/c/t1.c,t1.c}),
 Python
-(@url{@value{GITLAB-PREFIX}/tutorials/python/t1.py,t1.py})
-and Julia
-(@url{@value{GITLAB-PREFIX}/tutorials/julia/t1.jl,t1.jl}).
+(@url{@value{GITLAB-PREFIX}/tutorials/python/t1.py,t1.py}),
+Julia
+(@url{@value{GITLAB-PREFIX}/tutorials/julia/t1.jl,t1.jl})
+and Fortran
+(@url{@value{GITLAB-PREFIX}/tutorials/fortran/t1.f90,t1.f90}).
 
 @smallformat
 @verbatiminclude ../../tutorials/t1.geo
@@ -5289,9 +5293,11 @@ available in C++
 C
 (@url{@value{GITLAB-PREFIX}/tutorials/c/t2.c,t2.c}),
 Python
-(@url{@value{GITLAB-PREFIX}/tutorials/python/t2.py,t2.py})
-and Julia
-(@url{@value{GITLAB-PREFIX}/tutorials/julia/t2.jl,t2.jl}).
+(@url{@value{GITLAB-PREFIX}/tutorials/python/t2.py,t2.py}),
+Julia
+(@url{@value{GITLAB-PREFIX}/tutorials/julia/t2.jl,t2.jl})
+and Fortran
+(@url{@value{GITLAB-PREFIX}/tutorials/fortran/t2.f90,t2.f90}).
 
 @smallformat
 @verbatiminclude ../../tutorials/t2.geo
@@ -5309,9 +5315,11 @@ See
 Also available in C++
 (@url{@value{GITLAB-PREFIX}/tutorials/c++/t3.cpp,t3.cpp}),
 Python
-(@url{@value{GITLAB-PREFIX}/tutorials/python/t3.py,t3.py})
-and Julia
-(@url{@value{GITLAB-PREFIX}/tutorials/julia/t3.jl,t3.jl}).
+(@url{@value{GITLAB-PREFIX}/tutorials/python/t3.py,t3.py}),
+Julia
+(@url{@value{GITLAB-PREFIX}/tutorials/julia/t3.jl,t3.jl})
+and Fortran
+(@url{@value{GITLAB-PREFIX}/tutorials/fortran/t3.f90,t3.f90}).
 
 @smallformat
 @verbatiminclude ../../tutorials/t3.geo
@@ -5329,9 +5337,11 @@ See
 Also available in C++
 (@url{@value{GITLAB-PREFIX}/tutorials/c++/t4.cpp,t4.cpp}),
 Python
-(@url{@value{GITLAB-PREFIX}/tutorials/python/t4.py,t4.py})
-and Julia
-(@url{@value{GITLAB-PREFIX}/tutorials/julia/t4.jl,t4.jl}).
+(@url{@value{GITLAB-PREFIX}/tutorials/python/t4.py,t4.py}),
+Julia
+(@url{@value{GITLAB-PREFIX}/tutorials/julia/t4.jl,t4.jl})
+and Fortran
+(@url{@value{GITLAB-PREFIX}/tutorials/fortran/t4.f90,t4.f90}).
 
 @smallformat
 @verbatiminclude ../../tutorials/t4.geo
@@ -5349,9 +5359,11 @@ See
 Also available in C++
 (@url{@value{GITLAB-PREFIX}/tutorials/c++/t5.cpp,t5.cpp}),
 Python
-(@url{@value{GITLAB-PREFIX}/tutorials/python/t5.py,t5.py})
-and Julia
-(@url{@value{GITLAB-PREFIX}/tutorials/julia/t5.jl,t5.jl}).
+(@url{@value{GITLAB-PREFIX}/tutorials/python/t5.py,t5.py}),
+Julia
+(@url{@value{GITLAB-PREFIX}/tutorials/julia/t5.jl,t5.jl})
+and Fortran
+(@url{@value{GITLAB-PREFIX}/tutorials/fortran/t5.f90,t5.f90}).
 
 @smallformat
 @verbatiminclude ../../tutorials/t5.geo
@@ -5369,9 +5381,11 @@ See
 Also available in C++
 (@url{@value{GITLAB-PREFIX}/tutorials/c++/t6.cpp,t6.cpp}),
 C
-(@url{@value{GITLAB-PREFIX}/tutorials/c/t6.c,t6.c})
-and Python
-(@url{@value{GITLAB-PREFIX}/tutorials/python/t6.py,t6.py}).
+(@url{@value{GITLAB-PREFIX}/tutorials/c/t6.c,t6.c}),
+Python
+(@url{@value{GITLAB-PREFIX}/tutorials/python/t6.py,t6.py})
+and Fortran
+(@url{@value{GITLAB-PREFIX}/tutorials/fortran/t6.f90,t6.f90}).
 
 @smallformat
 @verbatiminclude ../../tutorials/t6.geo
@@ -5387,9 +5401,11 @@ and Python
 See
 @url{@value{GITLAB-PREFIX}/tutorials/t7.geo,t7.geo}.
 Also available in C++
-(@url{@value{GITLAB-PREFIX}/tutorials/c++/t7.cpp,t7.cpp})
-and Python
-(@url{@value{GITLAB-PREFIX}/tutorials/python/t7.py,t7.py}).
+(@url{@value{GITLAB-PREFIX}/tutorials/c++/t7.cpp,t7.cpp}),
+Python
+(@url{@value{GITLAB-PREFIX}/tutorials/python/t7.py,t7.py})
+and Fortran
+(@url{@value{GITLAB-PREFIX}/tutorials/fortran/t7.f90,t7.f90}).
 
 @smallformat
 @verbatiminclude ../../tutorials/t7.geo
@@ -5405,9 +5421,11 @@ and Python
 See
 @url{@value{GITLAB-PREFIX}/tutorials/t8.geo,t8.geo}.
 Also available in C++
-(@url{@value{GITLAB-PREFIX}/tutorials/c++/t8.cpp,t8.cpp})
-and Python
-(@url{@value{GITLAB-PREFIX}/tutorials/python/t8.py,t8.py}).
+(@url{@value{GITLAB-PREFIX}/tutorials/c++/t8.cpp,t8.cpp}),
+Python
+(@url{@value{GITLAB-PREFIX}/tutorials/python/t8.py,t8.py})
+and Fortran
+(@url{@value{GITLAB-PREFIX}/tutorials/fortran/t8.f90,t8.f90}).
 
 @smallformat
 @verbatiminclude ../../tutorials/t8.geo
@@ -5423,9 +5441,11 @@ and Python
 See
 @url{@value{GITLAB-PREFIX}/tutorials/t9.geo,t9.geo}.
 Also available in C++
-(@url{@value{GITLAB-PREFIX}/tutorials/c++/t9.cpp,t9.cpp})
-and Python
-(@url{@value{GITLAB-PREFIX}/tutorials/python/t9.py,t9.py}).
+(@url{@value{GITLAB-PREFIX}/tutorials/c++/t9.cpp,t9.cpp}),
+Python
+(@url{@value{GITLAB-PREFIX}/tutorials/python/t9.py,t9.py})
+and Fortran
+(@url{@value{GITLAB-PREFIX}/tutorials/fortran/t9.f90,t9.f90}).
 
 @smallformat
 @verbatiminclude ../../tutorials/t9.geo
@@ -5441,11 +5461,13 @@ and Python
 See
 @url{@value{GITLAB-PREFIX}/tutorials/t10.geo,t10.geo}.
 Also available in C++
-(@url{@value{GITLAB-PREFIX}/tutorials/c++/t10.cpp,t10.cpp})
-and Python
-(@url{@value{GITLAB-PREFIX}/tutorials/python/t10.py,t10.py})
-and Julia
-(@url{@value{GITLAB-PREFIX}/tutorials/julia/t10.jl,t10.jl}).
+(@url{@value{GITLAB-PREFIX}/tutorials/c++/t10.cpp,t10.cpp}),
+Python
+(@url{@value{GITLAB-PREFIX}/tutorials/python/t10.py,t10.py}),
+Julia
+(@url{@value{GITLAB-PREFIX}/tutorials/julia/t10.jl,t10.jl})
+and Fortran
+(@url{@value{GITLAB-PREFIX}/tutorials/fortran/t10.f90,t10.f90}).
 
 @smallformat
 @verbatiminclude ../../tutorials/t10.geo
@@ -5461,9 +5483,11 @@ and Julia
 See
 @url{@value{GITLAB-PREFIX}/tutorials/t11.geo,t11.geo}.
 Also available in C++
-(@url{@value{GITLAB-PREFIX}/tutorials/c++/t11.cpp,t11.cpp})
-and Python
-(@url{@value{GITLAB-PREFIX}/tutorials/python/t11.py,t11.py}).
+(@url{@value{GITLAB-PREFIX}/tutorials/c++/t11.cpp,t11.cpp}),
+Python
+(@url{@value{GITLAB-PREFIX}/tutorials/python/t11.py,t11.py})
+and Fortran
+(@url{@value{GITLAB-PREFIX}/tutorials/fortran/t11.f90,t11.f90}).
 
 @smallformat
 @verbatiminclude ../../tutorials/t11.geo
@@ -5479,9 +5503,11 @@ and Python
 See
 @url{@value{GITLAB-PREFIX}/tutorials/t12.geo,t12.geo}/
 Also available in C++
-(@url{@value{GITLAB-PREFIX}/tutorials/c++/t12.cpp,t12.cpp})
-and Python
-(@url{@value{GITLAB-PREFIX}/tutorials/python/t12.py,t12.py}).
+(@url{@value{GITLAB-PREFIX}/tutorials/c++/t12.cpp,t12.cpp}),
+Python
+(@url{@value{GITLAB-PREFIX}/tutorials/python/t12.py,t12.py})
+and Fortran
+(@url{@value{GITLAB-PREFIX}/tutorials/fortran/t12.f90,t12.f90}).
 
 @smallformat
 @verbatiminclude ../../tutorials/t12.geo
@@ -5497,9 +5523,11 @@ and Python
 See
 @url{@value{GITLAB-PREFIX}/tutorials/t13.geo,t13.geo}.
 Also available in C++
-(@url{@value{GITLAB-PREFIX}/tutorials/c++/t13.cpp,t13.cpp})
-and Python
-(@url{@value{GITLAB-PREFIX}/tutorials/python/t13.py,t13.py}).
+(@url{@value{GITLAB-PREFIX}/tutorials/c++/t13.cpp,t13.cpp}),
+Python
+(@url{@value{GITLAB-PREFIX}/tutorials/python/t13.py,t13.py})
+and Fortran
+(@url{@value{GITLAB-PREFIX}/tutorials/fortran/t13.f90,t13.f90}).
 
 @smallformat
 @verbatiminclude ../../tutorials/t13.geo
@@ -5515,9 +5543,11 @@ and Python
 See
 @url{@value{GITLAB-PREFIX}/tutorials/t14.geo,t14.geo}.
 Also available in C++
-(@url{@value{GITLAB-PREFIX}/tutorials/c++/t14.cpp,t14.cpp})
-and Python
-(@url{@value{GITLAB-PREFIX}/tutorials/python/t14.py,t14.py}).
+(@url{@value{GITLAB-PREFIX}/tutorials/c++/t14.cpp,t14.cpp}),
+Python
+(@url{@value{GITLAB-PREFIX}/tutorials/python/t14.py,t14.py})
+and Fortran
+(@url{@value{GITLAB-PREFIX}/tutorials/fortran/t14.f90,t14.f90}).
 
 @smallformat
 @verbatiminclude ../../tutorials/t14.geo
@@ -5533,9 +5563,11 @@ and Python
 See
 @url{@value{GITLAB-PREFIX}/tutorials/t15.geo,t15.geo}.
 Also available in C++
-(@url{@value{GITLAB-PREFIX}/tutorials/c++/t15.cpp,t15.cpp})
-and Python
-(@url{@value{GITLAB-PREFIX}/tutorials/python/t15.py,t15.py}).
+(@url{@value{GITLAB-PREFIX}/tutorials/c++/t15.cpp,t15.cpp}),
+Python
+(@url{@value{GITLAB-PREFIX}/tutorials/python/t15.py,t15.py})
+and Fortran
+(@url{@value{GITLAB-PREFIX}/tutorials/fortran/t15.f90,t15.f90}).
 
 @smallformat
 @verbatiminclude ../../tutorials/t15.geo
@@ -5555,9 +5587,11 @@ Also available in C++
 C
 (@url{@value{GITLAB-PREFIX}/tutorials/c/t16.c,t16.c}),
 Python
-(@url{@value{GITLAB-PREFIX}/tutorials/python/t16.py,t16.py})
-and Julia
-(@url{@value{GITLAB-PREFIX}/tutorials/julia/t16.jl,t16.jl}).
+(@url{@value{GITLAB-PREFIX}/tutorials/python/t16.py,t16.py}),
+Julia
+(@url{@value{GITLAB-PREFIX}/tutorials/julia/t16.jl,t16.jl})
+and Fortran
+(@url{@value{GITLAB-PREFIX}/tutorials/fortran/t16.f90,t16.f90}).
 
 @smallformat
 @verbatiminclude ../../tutorials/t16.geo
@@ -5573,9 +5607,11 @@ and Julia
 See
 @url{@value{GITLAB-PREFIX}/tutorials/t17.geo,t17.geo}.
 Also available in C++
-(@url{@value{GITLAB-PREFIX}/tutorials/c++/t17.cpp,t17.cpp})
-and Python
-(@url{@value{GITLAB-PREFIX}/tutorials/python/t17.py,t17.py}).
+(@url{@value{GITLAB-PREFIX}/tutorials/c++/t17.cpp,t17.cpp}),
+Python
+(@url{@value{GITLAB-PREFIX}/tutorials/python/t17.py,t17.py})
+and Fortran
+(@url{@value{GITLAB-PREFIX}/tutorials/fortran/t17.f90,t17.f90}).
 
 @smallformat
 @verbatiminclude ../../tutorials/t17.geo
@@ -5591,9 +5627,11 @@ and Python
 See
 @url{@value{GITLAB-PREFIX}/tutorials/t18.geo,t18.geo}.
 Also available in C++
-(@url{@value{GITLAB-PREFIX}/tutorials/c++/t18.cpp,t18.cpp})
-and Python
-(@url{@value{GITLAB-PREFIX}/tutorials/python/t18.py,t18.py}).
+(@url{@value{GITLAB-PREFIX}/tutorials/c++/t18.cpp,t18.cpp}),
+Python
+(@url{@value{GITLAB-PREFIX}/tutorials/python/t18.py,t18.py})
+and Fortran
+(@url{@value{GITLAB-PREFIX}/tutorials/fortran/t18.f90,t18.f90}).
 
 @smallformat
 @verbatiminclude ../../tutorials/t18.geo
@@ -5609,9 +5647,11 @@ and Python
 See
 @url{@value{GITLAB-PREFIX}/tutorials/t19.geo,t19.geo}.
 Also available in C++
-(@url{@value{GITLAB-PREFIX}/tutorials/c++/t19.cpp,t19.cpp})
-and Python
-(@url{@value{GITLAB-PREFIX}/tutorials/python/t19.py,t19.py}).
+(@url{@value{GITLAB-PREFIX}/tutorials/c++/t19.cpp,t19.cpp}),
+Python
+(@url{@value{GITLAB-PREFIX}/tutorials/python/t19.py,t19.py})
+and Fortran
+(@url{@value{GITLAB-PREFIX}/tutorials/fortran/t19.f90,t19.f90}).
 
 @smallformat
 @verbatiminclude ../../tutorials/t19.geo
@@ -5627,9 +5667,11 @@ and Python
 See
 @url{@value{GITLAB-PREFIX}/tutorials/t20.geo,t20.geo}.
 Also available in C++
-(@url{@value{GITLAB-PREFIX}/tutorials/c++/t20.cpp,t20.cpp})
-and Python
-(@url{@value{GITLAB-PREFIX}/tutorials/python/t20.py,t20.py}).
+(@url{@value{GITLAB-PREFIX}/tutorials/c++/t20.cpp,t20.cpp}),
+Python
+(@url{@value{GITLAB-PREFIX}/tutorials/python/t20.py,t20.py})
+and Fortran
+(@url{@value{GITLAB-PREFIX}/tutorials/fortran/t20.f90,t20.f90}).
 
 @smallformat
 @verbatiminclude ../../tutorials/t20.geo
@@ -5645,9 +5687,11 @@ and Python
 See
 @url{@value{GITLAB-PREFIX}/tutorials/t21.geo,t21.geo}.
 Also available in C++
-(@url{@value{GITLAB-PREFIX}/tutorials/c++/t21.cpp,t21.cpp})
-and Python
-(@url{@value{GITLAB-PREFIX}/tutorials/python/t21.py,t21.py}).
+(@url{@value{GITLAB-PREFIX}/tutorials/c++/t21.cpp,t21.cpp}),
+Python
+(@url{@value{GITLAB-PREFIX}/tutorials/python/t21.py,t21.py})
+and Fortran
+(@url{@value{GITLAB-PREFIX}/tutorials/fortran/t21.f90,t21.f90}).
 
 @smallformat
 @verbatiminclude ../../tutorials/t21.geo
diff --git a/tutorials/README.txt b/tutorials/README.txt
index 0abbccec5cf7577faf76c28b275168b5ead4d3d5..43aaeb37db1e667691fdc4e1199aec6aedf56c10 100644
--- a/tutorials/README.txt
+++ b/tutorials/README.txt
@@ -11,13 +11,14 @@ the command line, run "gmsh t1.geo" (which will launch the GUI) or "gmsh t1.geo
    Gmsh app. See the top-level `README.txt' file in the Gmsh source code for
    instructions on how to compile the app from source.
 
-The `c++', `c', `python' and `julia' subdirectories contain the C++, C, Python
-and Julia tutorials, written using the Gmsh Application Programming Interface
-(API). You will need the Gmsh dynamic library and the associated header files
-(for C++ and C) or modules (for Python and Julia) to run them. Each subdirectory
-contains additional information on how to run the tutorials for each supported
-language, as well as extended tutorials (starting with `x') introducing features
-available through the API but not available in `.geo' files.
+The `c++', `c', `python', `julia' and `fortran' subdirectories contain the C++,
+C, Python, Julia and Fortran tutorials, written using the Gmsh Application
+Programming Interface (API). You will need the Gmsh dynamic library and the
+associated header files (for C++ and C) or modules (for Python, Julia and
+Fortran) to run them. Each subdirectory contains additional information on how
+to run the tutorials for each supported language, as well as extended tutorials
+(starting with `x') introducing features available through the API but not
+available in `.geo' files.
 
  * A binary Software Development Kit (SDK) for Windows, Linux and macOS, that
    contains the dynamic Gmsh library and the associated header and module files,
diff --git a/tutorials/fortran/README.txt b/tutorials/fortran/README.txt
new file mode 100644
index 0000000000000000000000000000000000000000..1d06f5dd56cf4cb4369efde63dbc91a38decbfb1
--- /dev/null
+++ b/tutorials/fortran/README.txt
@@ -0,0 +1,33 @@
+This directory contains the Gmsh Fortran tutorials, written using the Gmsh Fortran API.
+
+To compile and run the Fortran tutorials, you need the Gmsh dynamic library and the
+associated Fortran module (`gmsh.f90'). These can be either obtained
+
+- from the binary Software Development Kit (SDK) available on the Gmsh website
+  https://gmsh.info/bin/, for Windows, Linux and macOS. Download and uncompress
+  the relevant gmsh*-sdk.* archive for your operating system. To compile the
+  first tutorial, assuming that you are currently in the root directory of the
+  SDK and that you are using the gfortran compiler:
+
+    gfortran -o t1 include/gmsh.f90 share/doc/gmsh/tutorials/fortran/t1.f90 -Llib -lgmsh
+
+  Then run
+
+    ./t1
+
+- by compiling the Gmsh source code. Follow these steps in the top-level
+  directory of the Gmsh source code:
+
+    mkdir build
+    cd build
+    cmake -DENABLE_BUILD_DYNAMIC=1 ..
+    make
+    make install
+    cd ..
+
+  Then, assuming that you are using the gcc compiler:
+
+    gfortran -o t1 /usr/local/include/gmsh.f90 t1.f90 -L/usr/local/lib -lgmsh
+    ./t1
+
+For other Fortran API examples, see the `examples/api' directory.
diff --git a/tutorials/fortran/t1.f b/tutorials/fortran/t1.f
deleted file mode 100644
index 809e49c946e1eca8916a686d09d3f42559a64d65..0000000000000000000000000000000000000000
--- a/tutorials/fortran/t1.f
+++ /dev/null
@@ -1,79 +0,0 @@
-c ---------------------------------------------------------------------------
-c
-c   Gmsh Fortran tutorial 1
-c
-c   Elementary entities (points, curves, surfaces), physical groups
-c
-c ---------------------------------------------------------------------------
-
-      include "gmshf.h"
-
-      program main
-      use, intrinsic :: iso_c_binding
-      use gmsh_fortran
-
-      implicit none
-      integer(c_int) :: ierr, p4, argc, itmp, i, ps, status, len
-      real(c_double) :: lc
-
-      integer(c_int) :: cl1(4) = (/4, 1, -2, 3/)
-      integer(c_int) :: s1(1) = (/1/)
-      integer(c_int) :: g5(3) = (/1, 2, 4/)
-      integer(c_int) :: g6(1) = (/1/)
-
-      type(c_ptr), allocatable :: argv(:)
-
-      type string
-        character(len = :, kind = c_char), allocatable :: item
-      end type string
-      type(string), allocatable, target :: tmp(:)
-
-      character(80) :: buf
-
-      lc = 1d - 2
-
-      argc = command_argument_count()
-      allocate(argv(argc + 2))
-      allocate(tmp(argc + 1))
-
-      do i = 0, argc
-        call get_command_argument(i, buf, len)
-        tmp(i + 1) % item = buf(1 : len) // c_null_char
-        argv(i + 1) = c_loc(tmp(i + 1) % item)
-      enddo
-      argv(argc + 2) = c_null_ptr
-
-      call gmshInitialize(argc + 1, argv, 1, 0, ierr)
-
-      call gmshModelAdd("t1" // c_null_char, ierr)
-      itmp = gmshModelGeoAddPoint(0d0, 0d0, 0d0, lc, 1, ierr)
-      itmp = gmshModelGeoAddPoint(0.1d0, 0d0, 0d0, lc, 2, ierr)
-      itmp = gmshModelGeoAddPoint(0.1d0, 0.3d0, 0d0, lc, 3, ierr)
-      p4 = gmshModelGeoAddPoint(0d0, 0.3d0, 0d0, lc, -1, ierr)
-
-      itmp = gmshModelGeoAddLine(1, 2, 1, ierr)
-      itmp = gmshModelGeoAddLine(3, 2, 2, ierr)
-      itmp = gmshModelGeoAddLine(3, p4, 3, ierr)
-      itmp = gmshModelGeoAddLine(p4, 1, 4, ierr)
-
-      itmp = gmshModelGeoAddCurveLoop(cl1, 4_8, 1, 0, ierr)
-      itmp = gmshModelGeoAddPlaneSurface(s1, 1_8, 1, ierr)
-
-      call gmshModelGeoSynchronize(ierr)
-      itmp = gmshModelAddPhysicalGroup(1, g5, 3_8, 5, ierr)
-      ps = gmshModelAddPhysicalGroup(2, g6, 1_8, -1, ierr)
-      call gmshModelSetPhysicalName(2, ps, "My surface" // c_null_char,
-     &     ierr)
-
-      call gmshModelMeshGenerate(2, ierr)
-      call gmshWrite("t1.msh" // c_null_char, ierr)
-
-c     call gmshFltkRun(ierr)
-
-      call gmshFinalize(ierr)
-
-      deallocate(tmp)
-      deallocate(argv)
-
-      stop
-      end
diff --git a/tutorials/fortran/t1.f90 b/tutorials/fortran/t1.f90
new file mode 100644
index 0000000000000000000000000000000000000000..f89ad433033c6b173ddef88119f5b8c60247b5c8
--- /dev/null
+++ b/tutorials/fortran/t1.f90
@@ -0,0 +1,178 @@
+! ---------------------------------------------------------------------------
+!
+!   Gmsh Fortran tutorial 1
+!
+!   Elementary entities (points, curves, surfaces), physical groups
+!
+! ---------------------------------------------------------------------------
+
+program t1
+use, intrinsic :: iso_c_binding
+use gmsh
+
+implicit none
+
+type(gmsh_t) :: gmsh
+integer(c_int) :: p4, r
+real(c_double) :: lc
+
+character(len=GMSH_API_MAX_STR_LEN) :: cmd
+
+! Before using any functions in the Python API, Gmsh must be initialized:
+call gmsh%initialize()
+
+! Next we add a new model named "t1" (if gmsh.model.add() is not called a new
+! unnamed model will be created on the fly, if necessary):
+call gmsh%model%add("t1")
+
+! The Fortran API provides direct access to each supported geometry (CAD)
+! kernel. The built-in kernel is used in this first tutorial: the corresponding
+! API functions have the `gmsh%model%geo' prefix.
+
+! The first type of `elementary entity' in Gmsh is a `Point'. To create a point
+! with the built-in CAD kernel, the Python API function is
+! gmsh.model.geo.addPoint():
+! - the first 3 arguments are the point coordinates (x, y, z)
+! - the next (optional) argument is the target mesh size close to the point
+! - the last (optional) argument is the point tag (a stricly positive integer
+!   that uniquely identifies the point)
+lc = 1e-2
+r = gmsh%model%geo%addPoint(0d0, 0d0, 0d0, lc, 1)
+
+! The distribution of the mesh element sizes will be obtained by interpolation
+! of these mesh sizes throughout the geometry. Another method to specify mesh
+! sizes is to use general mesh size Fields (see `t10.f90'). A particular case is
+! the use of a background mesh (see `t7.f90').
+!
+! If no target mesh size of provided, a default uniform coarse size will be used
+! for the model, based on the overall model size.
+!
+! We can then define some additional points. All points should have different
+! tags:
+r = gmsh%model%geo%addPoint(.1d0, 0d0, 0d0, lc, 2)
+r = gmsh%model%geo%addPoint(.1d0, .3d0, 0d0, lc, 3)
+
+! If the tag is not provided explicitly, a new tag is automatically created, and
+! returned by the function:
+p4 = gmsh%model%geo%addPoint(0d0, .3d0, 0d0, lc)
+
+! Curves are Gmsh's second type of elementery entities, and, amongst curves,
+! straight lines are the simplest. The API to create straight line segments with
+! the built-in kernel follows the same conventions: the first 2 arguments are
+! point tags (the start and end points of the line), and the last (optional one)
+! is the line tag.
+!
+! In the commands below, for example, the line 1 starts at point 1 and ends at
+! point 2.
+!
+! Note that curve tags are separate from point tags - hence we can reuse tag `1'
+! for our first curve. And as a general rule, elementary entity tags in Gmsh
+! have to be unique per geometrical dimension.
+r = gmsh%model%geo%addLine(1, 2, 1)
+r = gmsh%model%geo%addLine(3, 2, 2)
+r = gmsh%model%geo%addLine(3, p4, 3)
+r = gmsh%model%geo%addLine(4, 1, p4)
+
+! The third elementary entity is the surface. In order to define a simple
+! rectangular surface from the four curves defined above, a curve loop has first
+! to be defined. A curve loop is defined by an ordered list of connected curves,
+! a sign being associated with each curve (depending on the orientation of the
+! curve to form a loop). The API function to create curve loops takes a list
+! of integers as first argument, and the curve loop tag (which must be unique
+! amongst curve loops) as the second (optional) argument:
+r = gmsh%model%geo%addCurveLoop([4, 1, -2, 3], 1)
+
+! We can then define the surface as a list of curve loops (only one here,
+! representing the external contour, since there are no holes--see `t4.f90' for
+! an example of a surface with a hole):
+r = gmsh%model%geo%addPlaneSurface([1], 1)
+
+! Before they can be meshed (and, more generally, before they can be used by API
+! functions outside of the built-in CAD kernel functions), the CAD entities must
+! be synchronized with the Gmsh model, which will create the relevant Gmsh data
+! structures. This is achieved by the gmsh.model.geo.synchronize() API call for
+! the built-in CAD kernel. Synchronizations can be called at any time, but 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.
+call gmsh%model%geo%synchronize()
+
+! At this level, Gmsh knows everything to display the rectangular surface 1 and
+! to mesh it. An optional step is needed if we want to group elementary
+! geometrical entities into more meaningful groups, e.g. to define some
+! mathematical ("domain", "boundary"), functional ("left wing", "fuselage") or
+! material ("steel", "carbon") properties.
+!
+! Such groups are called "Physical Groups" in Gmsh. By default, if physical
+! groups are defined, Gmsh will export in output files only mesh elements that
+! belong to at least one physical group. (To force Gmsh to save all elements,
+! whether they belong to physical groups or not, set the `Mesh.SaveAll' option
+! to 1.) Physical groups are also identified by tags, i.e. strictly positive
+! integers, that should be unique per dimension (0D, 1D, 2D or 3D). Physical
+! groups can also be given names.
+!
+! Here we define a physical curve that groups the left, bottom and right curves
+! in a single group (with prescribed tag 5); and a physical surface with name
+! "My surface" (with an automatic tag) containing the geometrical surface 1:
+r = gmsh%model%addPhysicalGroup(1, [1, 2, 4], 5)
+r = gmsh%model%addPhysicalGroup(2, [1], name = "My surface")
+
+! We can then generate a 2D mesh...
+call gmsh%model%mesh%generate(2)
+
+! ... and save it to disk
+call gmsh%write("t1.msh")
+
+! Remember that by default, if physical groups are defined, Gmsh will export in
+! the output mesh file only those elements that belong to at least one physical
+! group. To force Gmsh to save all elements, you can use
+!
+! call gmsh%option%setNumber("Mesh.SaveAll", 1d0)
+
+! By default, Gmsh saves meshes in the latest version of the Gmsh mesh file
+! format (the `MSH' format). You can save meshes in other mesh formats by
+! specifying a filename with a different extension. For example
+!
+!   call gmsh%write("t1.unv")
+!
+! will save the mesh in the UNV format. You can also save the mesh in older
+! versions of the MSH format: simply set
+!
+!   call gmsh%option%setNumber("Mesh.MshFileVersion", x)
+!
+! for any version number `x'. As an alternative, you can also not specify the
+! format explicitly, and just choose a filename with the `.msh2' or `.msh4'
+! extension.
+
+! To visualize the model we can run the graphical user interface with
+! `call gmsh%fltk%run()'. Here we run it only if "-nopopup" is not provided in the
+! command line arguments:
+call get_command(cmd)
+if (index(cmd, "-nopopup") == 0) call gmsh%fltk%run()
+
+
+! Note that starting with Gmsh 3.0, models can be built using other geometry
+! kernels than the default "built-in" kernel. To use the OpenCASCADE CAD kernel
+! instead of the built-in kernel, you should use the functions with the
+! `gmsh%model%occ' prefix.
+!
+! Different CAD kernels have different features. With OpenCASCADE, instead of
+! defining the surface by successively defining 4 points, 4 curves and 1 curve
+! loop, one can define the rectangular surface directly with
+!
+! r = gmsh%model%occ%addRectangle(.2d0, 0d0, 0d0, .1d0, .3d0)
+!
+! After synchronization with the Gmsh model with
+!
+! call gmsh%model%occ%synchronize()
+!
+! the underlying curves and points could be accessed with
+! call gmsh%model%getBoundary()
+!
+! See e.g. `t16.f90', `t18.f90', `t19.f90' or `t20.f90' for complete examples based
+! on OpenCASCADE, and `examples/api' for more.
+
+! This should be called when you are done using the Gmsh Python API:
+call gmsh%finalize()
+
+end program t1
diff --git a/tutorials/fortran/t10.f90 b/tutorials/fortran/t10.f90
new file mode 100644
index 0000000000000000000000000000000000000000..f4031e77ee761a8e814bce97b990f8d42cf8ee66
--- /dev/null
+++ b/tutorials/fortran/t10.f90
@@ -0,0 +1,164 @@
+! ------------------------------------------------------------------------------
+!
+!  Gmsh Fortran tutorial 10
+!
+!  Mesh size fields
+!
+! ------------------------------------------------------------------------------
+
+! In addition to specifying target mesh sizes at the points of the geometry (see
+! `t1.f90') or using a background mesh (see `t7.f90'), you can use general mesh
+! size "Fields".
+program t10
+
+use, intrinsic :: iso_c_binding
+use gmsh
+
+implicit none
+type(gmsh_t) :: gmsh
+integer(c_int) :: ret
+real(c_double), parameter :: lc = .15
+character(len=GMSH_API_MAX_STR_LEN) :: cmd, str
+
+call gmsh%initialize()
+
+call gmsh%model%add("t10")
+
+! Let's create a simple rectangular geometry:
+ret = gmsh%model%geo%addPoint(0.0d0, 0.0d0, 0d0, lc, 1)
+ret = gmsh%model%geo%addPoint(1.0d0, 0.0d0, 0d0, lc, 2)
+ret = gmsh%model%geo%addPoint(1.0d0, 1.0d0, 0d0, lc, 3)
+ret = gmsh%model%geo%addPoint(0.0d0, 1.0d0, 0d0, lc, 4)
+ret = gmsh%model%geo%addPoint(0.2d0, 0.5d0, 0d0, lc, 5)
+
+ret = gmsh%model%geo%addLine(1, 2, 1)
+ret = gmsh%model%geo%addLine(2, 3, 2)
+ret = gmsh%model%geo%addLine(3, 4, 3)
+ret = gmsh%model%geo%addLine(4, 1, 4)
+
+ret = gmsh%model%geo%addCurveLoop([1, 2, 3, 4], 5)
+ret = gmsh%model%geo%addPlaneSurface([5], 6)
+
+call gmsh%model%geo%synchronize()
+
+! Say we would like to obtain mesh elements with size lc/30 near curve 2 and
+! point 5, and size lc elsewhere. To achieve this, we can use two fields:
+! "Distance", and "Threshold". We first define a Distance field (`Field[1]') on
+! points 5 and on curve 2. This field returns the distance to point 5 and to
+! (100 equidistant points on) curve 2.
+ret = gmsh%model%mesh%field%add("Distance", 1)
+call gmsh%model%mesh%field%setNumbers(1, "PointsList", [5d0])
+call gmsh%model%mesh%field%setNumbers(1, "CurvesList", [2d0])
+call gmsh%model%mesh%field%setNumber(1, "Sampling", 100d0)
+
+! We then define a `Threshold' field, which uses the return value of the
+! `Distance' field 1 in order to define a simple change in element size
+! depending on the computed distances
+!
+! SizeMax -                     /------------------
+!                              /
+!                             /
+!                            /
+! SizeMin -o----------------/
+!          |                |    |
+!        Point         DistMin  DistMax
+ret = gmsh%model%mesh%field%add("Threshold", 2)
+call gmsh%model%mesh%field%setNumber(2, "InField", 1d0)
+call gmsh%model%mesh%field%setNumber(2, "SizeMin", lc / 30)
+call gmsh%model%mesh%field%setNumber(2, "SizeMax", lc)
+call gmsh%model%mesh%field%setNumber(2, "DistMin", 0.15d0)
+call gmsh%model%mesh%field%setNumber(2, "DistMax", 0.5d0)
+
+! Say we want to modulate the mesh element sizes using a mathematical function
+! of the spatial coordinates. We can do this with the MathEval field:
+ret = gmsh%model%mesh%field%add("MathEval", 3)
+call gmsh%model%mesh%field%setString(3, "F", &
+                                "Cos(4*3.14*x) * Sin(4*3.14*y) / 10 + 0.101")
+
+! We could also combine MathEval with values coming from other fields. For
+! example, let's define a `Distance' field around point 1
+ret = gmsh%model%mesh%field%add("Distance", 4)
+call gmsh%model%mesh%field%setNumbers(4, "PointsList", [1d0])
+
+! We can then create a `MathEval' field with a function that depends on the
+! return value of the `Distance' field 4, i.e., depending on the distance to
+! point 1 (here using a cubic law, with minimum element size = lc / 100)
+ret = gmsh%model%mesh%field%add("MathEval", 5)
+write(str, '(f10.3)') lc / 100
+call gmsh%model%mesh%field%setString(5, "F", "F4^3 + "//trim(str))
+
+! We could also use a `Box' field to impose a step change in element sizes
+! inside a box
+ret = gmsh%model%mesh%field%add("Box", 6)
+call gmsh%model%mesh%field%setNumber(6, "VIn", lc / 15)
+call gmsh%model%mesh%field%setNumber(6, "VOut", lc)
+call gmsh%model%mesh%field%setNumber(6, "XMin", 0.3d0)
+call gmsh%model%mesh%field%setNumber(6, "XMax", 0.6d0)
+call gmsh%model%mesh%field%setNumber(6, "YMin", 0.3d0)
+call gmsh%model%mesh%field%setNumber(6, "YMax", 0.6d0)
+call gmsh%model%mesh%field%setNumber(6, "Thickness", 0.3d0)
+
+! Many other types of fields are available: see the reference manual for a
+! complete list. You can also create fields directly in the graphical user
+! interface by selecting `Define->Size fields' in the `Mesh' module.
+
+! Let's use the minimum of all the fields as the background mesh field:
+ret = gmsh%model%mesh%field%add("Min", 7)
+call gmsh%model%mesh%field%setNumbers(7, "FieldsList", [2d0, 3d0, 5d0, 6d0])
+
+call gmsh%model%mesh%field%setAsBackgroundMesh(7)
+
+! The API also allows to set a global mesh size callback, which is called each
+! time the mesh size is queried
+call gmsh%model%mesh%setSizeCallback(c_funloc(meshSizeCallback))
+
+! To determine the size of mesh elements, Gmsh locally computes the minimum of
+!
+! 1) the size of the model bounding box;
+! 2) if `Mesh.MeshSizeFromPoints' is set, the mesh size specified at geometrical
+!    points;
+! 3) if `Mesh.MeshSizeFromCurvature' is positive, the mesh size based on
+!    curvature (the value specifying the number of elements per 2 * pi rad);
+! 4) the background mesh field;
+! 5) any per-entity mesh size constraint;
+!
+! The value can then be further modified by the mesh size callback, if any,
+! before being constrained in the interval [`Mesh.MeshSizeMin',
+! `Mesh.MeshSizeMax'] and multiplied by `Mesh.MeshSizeFactor'.  In addition,
+! boundary mesh sizes are interpolated inside surfaces and/or volumes depending
+! on the value of `Mesh.MeshSizeExtendFromBoundary' (which is set by default).
+!
+! When the element size is fully specified by a background mesh (as it is in
+! this example), it is thus often desirable to set
+
+call gmsh%option%setNumber("Mesh.MeshSizeExtendFromBoundary", 0d0)
+call gmsh%option%setNumber("Mesh.MeshSizeFromPoints", 0d0)
+call gmsh%option%setNumber("Mesh.MeshSizeFromCurvature", 0d0)
+
+! This will prevent over-refinement due to small mesh sizes on the boundary.
+
+! Finally, while the default "Frontal-Delaunay" 2D meshing algorithm
+! (Mesh.Algorithm = 6) usually leads to the highest quality meshes, the
+! "Delaunay" algorithm (mesh%Algorithm = 5) will handle complex mesh size fields
+! better - in particular size fields with large element size gradients:
+
+call gmsh%option%setNumber("Mesh.Algorithm", 5d0)
+
+call gmsh%model%mesh%generate(2)
+call gmsh%write("t10.msh")
+
+! Launch the GUI to see the results:
+call get_command(cmd)
+if (index(cmd, "-nopopup") == 0) call gmsh%fltk%run()
+
+call gmsh%finalize()
+
+contains
+
+real(c_double) function meshSizeCallback(dim, tag, x, y, z, lc) result(val)
+  integer(c_int), value, intent(in) :: dim, tag
+  real(c_double), value, intent(in) :: x, y, z, lc
+  val = min(lc, 0.02 * x + 0.01)
+end function meshSizeCallback
+
+end program t10
diff --git a/tutorials/fortran/t11.f90 b/tutorials/fortran/t11.f90
new file mode 100644
index 0000000000000000000000000000000000000000..fe4223c3c0067f2df970898ae8258b178f5ad79a
--- /dev/null
+++ b/tutorials/fortran/t11.f90
@@ -0,0 +1,106 @@
+! ------------------------------------------------------------------------------
+!
+!  Gmsh Fortran tutorial 11
+!
+!  Unstructured quadrangular meshes
+!
+! ------------------------------------------------------------------------------
+
+program t11
+
+use, intrinsic :: iso_c_binding
+use gmsh
+
+implicit none
+type(gmsh_t) :: gmsh
+type(gmsh_model_mesh_field_t) :: field
+integer(c_int) :: ret, p1, p2, p3, p4, l1, l2, l3, l4, cl, pl
+real(c_double), parameter :: lc = .15
+character(len=GMSH_API_MAX_STR_LEN) :: cmd
+
+call gmsh%initialize()
+
+call gmsh%model%add("t11")
+
+! We have seen in tutorials `t3.f90' and `t6.f90' that extruded and transfinite
+! meshes can be "recombined" into quads, prisms or hexahedra. Unstructured
+! meshes can be recombined in the same way. Let's define a simple geometry with
+! an analytical mesh size field:
+
+p1 = gmsh%model%geo%addPoint(-1.25d0, -.5d0, 0d0)
+p2 = gmsh%model%geo%addPoint(+1.25d0, -.5d0, 0d0)
+p3 = gmsh%model%geo%addPoint(+1.25d0, 1.25d0, 0d0)
+p4 = gmsh%model%geo%addPoint(-1.25d0, 1.25d0, 0d0)
+
+l1 = gmsh%model%geo%addLine(p1, p2)
+l2 = gmsh%model%geo%addLine(p2, p3)
+l3 = gmsh%model%geo%addLine(p3, p4)
+l4 = gmsh%model%geo%addLine(p4, p1)
+
+cl = gmsh%model%geo%addCurveLoop([l1, l2, l3, l4])
+pl = gmsh%model%geo%addPlaneSurface([cl])
+
+call gmsh%model%geo%synchronize()
+
+ret = field%add("MathEval", 1)
+call field%setString(1, "F", "0.01*(1.0+30.*(y-x*x)*(y-x*x) + (1-x)*(1-x))")
+call field%setAsBackgroundMesh(1)
+
+! To generate quadrangles instead of triangles, we can simply add
+call gmsh%model%mesh%setRecombine(2, pl)
+
+! If we'd had several surfaces, we could have used the global option
+! "Mesh.RecombineAll":
+!
+! gmsh%option.setNumber("Mesh.RecombineAll", 1)
+
+! The default recombination algorithm is called "Blossom": it uses a minimum
+! cost perfect matching algorithm to generate fully quadrilateral meshes from
+! triangulations. More details about the algorithm can be found in the
+! following paper: J.-F. Remacle, J. Lambrechts, B. Seny, E. Marchandise,
+! A. Johnen and C. Geuzaine, "Blossom-Quad: a non-uniform quadrilateral mesh
+! generator using a minimum cost perfect matching algorithm", International
+! Journal for Numerical Methods in Engineering 89, pp. 1102-1119, 2012.
+
+! For even better 2D (planar) quadrilateral meshes, you can try the
+! experimental "Frontal-Delaunay for quads" meshing algorithm, which is a
+! triangulation algorithm that enables to create right triangles almost
+! everywhere: J.-F. Remacle, F. Henrotte, T. Carrier-Baudouin, E. Bechet,
+! E. Marchandise, C. Geuzaine and T. Mouton. A frontal Delaunay quad mesh
+! generator using the L^inf norm. International Journal for Numerical Methods
+! in Engineering, 94, pp. 494-512, 2013. Uncomment the following line to try
+! the Frontal-Delaunay algorithms for quads:
+!
+! gmsh%option.setNumber("Mesh.Algorithm", 8)
+
+! The default recombination algorithm might leave some triangles in the mesh, if
+! recombining all the triangles leads to badly shaped quads. In such cases, to
+! generate full-quad meshes, you can either subdivide the resulting hybrid mesh
+! (with `Mesh.SubdivisionAlgorithm' set to 1), or use the full-quad
+! recombination algorithm, which will automatically perform a coarser mesh
+! followed by recombination, smoothing and subdivision. Uncomment the following
+! line to try the full-quad algorithm:
+!
+! gmsh%option.setNumber("Mesh.RecombinationAlgorithm", 2) ! or 3
+
+! You can also set the subdivision step alone, with
+!
+! gmsh%option.setNumber("Mesh.SubdivisionAlgorithm", 1)
+
+call gmsh%model%mesh%generate(2)
+
+! Note that you could also apply the recombination algorithm and/or the
+! subdivision step explicitly after meshing, as follows:
+!
+! gmsh%model%mesh%generate(2)
+! gmsh%model%mesh%recombine()
+! gmsh%option.setNumber("Mesh.SubdivisionAlgorithm", 1)
+! gmsh%model%mesh%refine()
+
+! Launch the GUI to see the results:
+call get_command(cmd)
+if (index(cmd, "-nopopup") == 0) call gmsh%fltk%run()
+
+call gmsh%finalize()
+
+end program t11
diff --git a/tutorials/fortran/t12.f90 b/tutorials/fortran/t12.f90
new file mode 100644
index 0000000000000000000000000000000000000000..3ea498c8557a6b0825f2f109f9e2215108055716
--- /dev/null
+++ b/tutorials/fortran/t12.f90
@@ -0,0 +1,103 @@
+! ------------------------------------------------------------------------------
+!
+!  Gmsh Fortran tutorial 12
+!
+!  Cross-patch meshing with compounds
+!
+! ------------------------------------------------------------------------------
+
+! "Compound" meshing constraints allow to generate meshes across surface
+! boundaries, which can be useful e.g. for imported CAD models (e.g. STEP) with
+! undesired small features.
+
+! When a `setCompound()' meshing constraint is given, at mesh generation time
+! Gmsh
+!  1. meshes the underlying elementary geometrical entities, individually
+!  2. creates a discrete entity that combines all the individual meshes
+!  3. computes a discrete parametrization (i.e. a piece-wise linear mapping)
+!     on this discrete entity
+!  4. meshes the discrete entity using this discrete parametrization instead
+!     of the underlying geometrical description of the underlying elementary
+!     entities making up the compound
+!  5. optionally, reclassifies the mesh elements and nodes on the original
+!     entities
+
+! Step 3. above can only be performed if the mesh resulting from the
+! combination of the individual meshes can be reparametrized, i.e. if the shape
+! is "simple enough". If the shape is not amenable to reparametrization, you
+! should create a full mesh of the geometry and first re-classify it to
+! generate patches amenable to reparametrization (see `t13.f90').
+
+! The mesh of the individual entities performed in Step 1. should usually be
+! finer than the desired final mesh; this can be controlled with the
+! `Mesh.CompoundMeshSizeFactor' option.
+
+! The optional reclassification on the underlying elementary entities in Step
+! 5. is governed by the `Mesh.CompoundClassify' option.
+
+program t12
+
+use, intrinsic :: iso_c_binding
+use gmsh
+
+implicit none
+type(gmsh_t) :: gmsh
+integer(c_int) :: ret
+real(c_double), parameter :: lc = .1
+character(len=GMSH_API_MAX_STR_LEN) :: cmd
+
+call gmsh%initialize()
+
+ret = gmsh%model%geo%addPoint(0.0d0, 0.0d0, 0.0d0, lc, 1)
+ret = gmsh%model%geo%addPoint(1.0d0, 0.0d0, 0.0d0, lc, 2)
+ret = gmsh%model%geo%addPoint(1.0d0, 1.0d0, 0.5d0, lc, 3)
+ret = gmsh%model%geo%addPoint(0.0d0, 1.0d0, 0.4d0, lc, 4)
+ret = gmsh%model%geo%addPoint(0.3d0, 0.2d0, 0.0d0, lc, 5)
+ret = gmsh%model%geo%addPoint(0.0d0, 0.01d0, 0.01d0, lc, 6)
+ret = gmsh%model%geo%addPoint(0.0d0, 0.02d0, 0.02d0, lc, 7)
+ret = gmsh%model%geo%addPoint(1.0d0, 0.05d0, 0.02d0, lc, 8)
+ret = gmsh%model%geo%addPoint(1.0d0, 0.32d0, 0.02d0, lc, 9)
+
+ret = gmsh%model%geo%addLine(1, 2, 1)
+ret = gmsh%model%geo%addLine(2, 8, 2)
+ret = gmsh%model%geo%addLine(8, 9, 3)
+ret = gmsh%model%geo%addLine(9, 3, 4)
+ret = gmsh%model%geo%addLine(3, 4, 5)
+ret = gmsh%model%geo%addLine(4, 7, 6)
+ret = gmsh%model%geo%addLine(7, 6, 7)
+ret = gmsh%model%geo%addLine(6, 1, 8)
+ret = gmsh%model%geo%addSpline([7, 5, 9], 9)
+ret = gmsh%model%geo%addLine(6, 8, 10)
+
+ret = gmsh%model%geo%addCurveLoop([5, 6, 9, 4], 11)
+ret = gmsh%model%geo%addSurfaceFilling([11], 1)
+
+ret = gmsh%model%geo%addCurveLoop([-9, 3, 10, 7], 13)
+ret = gmsh%model%geo%addSurfaceFilling([13], 5)
+
+ret = gmsh%model%geo%addCurveLoop([-10, 2, 1, 8], 15)
+ret = gmsh%model%geo%addSurfaceFilling([15], 10)
+
+call gmsh%model%geo%synchronize()
+
+! Treat curves 2, 3 and 4 as a single curve when meshing (i.e. mesh across
+! points 6 and 7)
+call gmsh%model%mesh%setCompound(1, [2, 3, 4])
+
+! Idem with curves 6, 7 and 8
+call gmsh%model%mesh%setCompound(1, [6, 7, 8])
+
+! Treat surfaces 1, 5 and 10 as a single surface when meshing (i.e. mesh across
+! curves 9 and 10)
+call gmsh%model%mesh%setCompound(2, [1, 5, 10])
+
+call gmsh%model%mesh%generate(2)
+call gmsh%write('t12.msh')
+
+! Launch the GUI to see the results:
+call get_command(cmd)
+if (index(cmd, "-nopopup") == 0) call gmsh%fltk%run()
+
+call gmsh%finalize()
+
+end program t12
diff --git a/tutorials/fortran/t13.f90 b/tutorials/fortran/t13.f90
new file mode 100644
index 0000000000000000000000000000000000000000..f3cf9f911991786a0488c73766c8a0069b3cc4c4
--- /dev/null
+++ b/tutorials/fortran/t13.f90
@@ -0,0 +1,150 @@
+! ------------------------------------------------------------------------------
+!
+!  Gmsh Fortran tutorial 13
+!
+!  Remeshing an STL file without an underlying CAD model
+!
+! ------------------------------------------------------------------------------
+
+program t13
+
+use, intrinsic :: iso_c_binding
+use gmsh
+
+implicit none
+type(gmsh_t) :: gmsh
+integer(c_int) :: ret
+real(c_double), parameter :: lc = .1
+character(len=GMSH_API_MAX_STR_LEN) :: cmd
+
+call gmsh%initialize()
+! Create ONELAB parameters with remeshing options:
+call gmsh%onelab%set('['//&
+  '{'//&
+    '"type":"number",'//&
+    '"name":"Parameters/Angle for surface detection",'//&
+    '"values":[40],'//&
+    '"min":20,'//&
+    '"max":120,'//&
+    '"step":1'//&
+  '},'//&
+  '{'//&
+    '"type":"number",'//&
+    '"name":"Parameters/Create surfaces guaranteed to be parametrizable",'//&
+    '"values":[0],'//&
+    '"choices":[0, 1]'//&
+  '},'//&
+  '{'//&
+    '"type":"number",'//&
+    '"name":"Parameters/Apply funny mesh size field?",'//&
+    '"values":[0],'//&
+    '"choices":[0, 1]'//&
+  '}'//&
+']')
+
+! Create the geometry and mesh it:
+call createGeometryAndMesh()
+
+call get_command(cmd)
+if (index(cmd, "-nopopup") == 0) then
+    call gmsh%fltk%initialize()
+    do while (transfer(gmsh%fltk%isAvailable(), .true.) .and. checkForEvent())
+        call gmsh%fltk%wait()
+    end do
+end if
+
+call gmsh%finalize()
+
+contains
+
+subroutine createGeometryAndMesh()
+    real(c_double) :: curveAngle, angle, forceParametrizablePatches
+    real(c_double), allocatable :: tmp(:)
+    integer(c_int), allocatable :: s(:,:)
+    integer(c_int) :: l, f
+    logical :: includeBoundary
+    ! Clear all models and merge an STL mesh that we would like to remesh (from
+    ! the parent directory):
+    call gmsh%clear()
+    call gmsh%merge('../t13_data.stl')
+
+    ! We first classify ("color") the surfaces by splitting the original surface
+    ! along sharp geometrical features. This will create new discrete surfaces,
+    ! curves and points.
+
+    ! Angle between two triangles above which an edge is considered as sharp,
+    ! retrieved from the ONELAB database (see below):
+    call gmsh%onelab%getNumber('Parameters/Angle for surface detection', tmp)
+    angle = tmp(1); deallocate(tmp)
+
+    ! For complex geometries, patches can be too complex, too elongated or too
+    ! large to be parametrized; setting the following option will force the
+    ! creation of patches that are amenable to reparametrization:
+    call gmsh%onelab%getNumber(&
+        'Parameters/Create surfaces guaranteed to be parametrizable', tmp)
+    forceParametrizablePatches = tmp(1); deallocate(tmp)
+
+    ! For open surfaces include the boundary edges in the classification
+    ! process:
+    includeBoundary = .true.
+
+    ! Force curves to be split on given angle:
+    curveAngle = 180
+
+    call gmsh%model%mesh%classifySurfaces(angle * M_PI / 180., includeBoundary, &
+                                          transfer(forceParametrizablePatches, .false.), &
+                                          curveAngle * M_PI / 180.)
+
+    ! Create a geometry for all the discrete curves and surfaces in the mesh, by
+    ! computing a parametrization for each one
+    call gmsh%model%mesh%createGeometry()
+
+    ! Note that if a CAD model (e.g. as a STEP file, see `t20.f90') is available
+    ! instead of an STL mesh, it is usually better to use that CAD model instead
+    ! of the geometry created by reparametrizing the mesh% Indeed, CAD
+    ! geometries will in general be more accurate, with smoother
+    ! parametrizations, and will lead to more efficient and higher quality
+    ! meshing. Discrete surface remeshing in Gmsh is optimized to handle dense
+    ! STL meshes coming from e.g. imaging systems, where no CAD is available; it
+    ! is less well suited for the poor quality STL triangulations (optimized for
+    ! size, with e.g. very elongated triangles) that are usually generated by
+    ! CAD tools for e.g. 3D printing.
+
+    ! Create a volume from all the surfaces
+    call gmsh%model%getEntities(s, dim=2)
+    l = gmsh%model%geo%addSurfaceLoop(s(2, :))
+    ret = gmsh%model%geo%addVolume([l])
+
+    call gmsh%model%geo%synchronize()
+
+    ! We specify element sizes imposed by a size field, just because we can :-)
+    f = gmsh%model%mesh%field%add("MathEval")
+    call gmsh%onelab%getNumber('Parameters/Apply funny mesh size field?', tmp)
+    if (size(tmp)> 1) then
+        call gmsh%model%mesh%field%setString(f, "F", "2*Sin((x+y)/5) + 3")
+    else
+        call gmsh%model%mesh%field%setString(f, "F", "4")
+    end if
+    call gmsh%model%mesh%field%setAsBackgroundMesh(f)
+
+    call gmsh%model%mesh%generate(3)
+    call gmsh%write('t13.msh')
+
+end subroutine createGeometryAndMesh
+
+
+! Launch the GUI and handle the "check" event to recreate the geometry and mesh
+! with new parameters if necessary:
+logical function checkForEvent()
+    character(len=GMSH_API_MAX_STR_LEN), allocatable :: action(:)
+    checkForEvent = .false.
+    call gmsh%onelab%getString("ONELAB/Action", action)
+    if (size(action) > 1 .and. trim(action(1)) == "check") then
+        call gmsh%onelab%setString("ONELAB/Action", [""])
+        call createGeometryAndMesh()
+        call gmsh%graphics%draw()
+    end if
+    checkForEvent = .true.
+end function checkForEvent
+
+end program t13
diff --git a/tutorials/fortran/t14.f90 b/tutorials/fortran/t14.f90
new file mode 100644
index 0000000000000000000000000000000000000000..d844fb7b20b6e1507993547409dd8ab6e05e335c
--- /dev/null
+++ b/tutorials/fortran/t14.f90
@@ -0,0 +1,155 @@
+! ------------------------------------------------------------------------------
+!
+!  Gmsh Fortran tutorial 14
+!
+!  Homology and cohomology computation
+!
+! ------------------------------------------------------------------------------
+
+! Homology computation in Gmsh finds representative chains of (relative)
+! (co)homology space bases using a mesh of a model%  The representative basis
+! chains are stored in the mesh as physical groups of Gmsh, one for each chain.
+
+program t14
+
+use, intrinsic :: iso_c_binding
+use gmsh
+
+implicit none
+type(gmsh_t) :: gmsh
+integer(c_int) :: ret, domain_tag, domain_physical_tag, terminals_physical_tag, &
+                  boundary_physical_tag, complement_physical_tag
+integer(c_int), allocatable :: e(:,:), terminal_tags(:), boundary_dimtags(:,:), &
+                               boundary_tags(:), complement_tags(:)
+real(c_double), parameter :: lc = .1
+real(c_double) :: m, h
+character(len=GMSH_API_MAX_STR_LEN) :: cmd
+
+call gmsh%initialize()
+
+! Create an example geometry
+call gmsh%model%add("t14")
+
+m = 0.5  ! mesh size
+h = 2  ! geometry height in the z-direction
+
+ret = gmsh%model%geo%addPoint(00d0, 00d0, 0d0, m, 1)
+ret = gmsh%model%geo%addPoint(10d0, 00d0, 0d0, m, 2)
+ret = gmsh%model%geo%addPoint(10d0, 10d0, 0d0, m, 3)
+ret = gmsh%model%geo%addPoint(00d0, 10d0, 0d0, m, 4)
+
+ret = gmsh%model%geo%addPoint(4d0, 4d0, 0d0, m, 5)
+ret = gmsh%model%geo%addPoint(6d0, 4d0, 0d0, m, 6)
+ret = gmsh%model%geo%addPoint(6d0, 6d0, 0d0, m, 7)
+ret = gmsh%model%geo%addPoint(4d0, 6d0, 0d0, m, 8)
+
+ret = gmsh%model%geo%addPoint(2d0, 0d0, 0d0, m, 9)
+ret = gmsh%model%geo%addPoint(8d0, 0d0, 0d0, m, 10)
+ret = gmsh%model%geo%addPoint(2d0, 10d0, 0d0, m, 11)
+ret = gmsh%model%geo%addPoint(8d0, 10d0, 0d0, m, 12)
+
+ret = gmsh%model%geo%addLine(1, 9, 1)
+ret = gmsh%model%geo%addLine(9, 10, 2)
+ret = gmsh%model%geo%addLine(10, 2, 3)
+
+ret = gmsh%model%geo%addLine(2, 3, 4)
+ret = gmsh%model%geo%addLine(3, 12, 5)
+ret = gmsh%model%geo%addLine(12, 11, 6)
+
+ret = gmsh%model%geo%addLine(11, 4, 7)
+ret = gmsh%model%geo%addLine(4, 1, 8)
+ret = gmsh%model%geo%addLine(5, 6, 9)
+
+ret = gmsh%model%geo%addLine(6, 7, 10)
+ret = gmsh%model%geo%addLine(7, 8, 11)
+ret = gmsh%model%geo%addLine(8, 5, 12)
+
+ret = gmsh%model%geo%addCurveLoop([6, 7, 8, 1, 2, 3, 4, 5], 13)
+ret = gmsh%model%geo%addCurveLoop([11, 12, 9, 10], 14)
+ret = gmsh%model%geo%addPlaneSurface([13, 14], 15)
+
+call gmsh%model%geo%extrude(reshape([2, 15], [2, 1]), 0d0, 0d0, h, outDimTags=e)
+
+call gmsh%model%geo%synchronize()
+
+! Create physical groups, which are used to define the domain of the
+! (co)homology computation and the subdomain of the relative (co)homology
+! computation.
+
+! Whole domain
+domain_tag = e(2,2)
+domain_physical_tag = 1001
+ret = gmsh%model%addPhysicalGroup(dim=3, tags=[domain_tag], tag=domain_physical_tag, name="Whole domain")
+
+! Four "terminals" of the model
+! terminal_tags = [e[3][1], e[5][1], e[7][1], e[9][1]]
+terminal_tags = [e(2,4), e(2,6), e(2,7), e(2,9)]
+terminals_physical_tag = 2001
+ret = gmsh%model%addPhysicalGroup(dim=2, &
+                                  tags=terminal_tags, &
+                                  tag=terminals_physical_tag, &
+                                  name="Terminals")
+
+! Find domain boundary tags
+call gmsh%model%getBoundary(dimTags=reshape([3, domain_tag], [2, 1]), &
+                            oriented=.false.,&
+                            outDimTags=boundary_dimtags)
+
+boundary_tags = boundary_dimtags(2,:)
+complement_tags = pack(boundary_dimtags(2,:), boundary_dimtags(2,:) == terminal_tags)
+
+! Whole domain surface
+boundary_physical_tag = 2002
+ret = gmsh%model%addPhysicalGroup(dim=2, &
+                                  tags=boundary_tags, &
+                                  tag=boundary_physical_tag, &
+                                  name="Boundary")
+
+! Complement of the domain surface with respect to the four terminals
+complement_physical_tag = 2003
+ret = gmsh%model%addPhysicalGroup(dim=2, &
+                                  tags=complement_tags, &
+                                  tag=complement_physical_tag, &
+                                  name="Complement")
+
+! Find bases for relative homology spaces of the domain modulo the four
+! terminals.
+call gmsh%model%mesh%addHomologyRequest("Homology", domainTags=[domain_physical_tag], &
+                                        subdomainTags=[terminals_physical_tag], &
+                                        dims=[0, 1, 2, 3])
+
+! Find homology space bases isomorphic to the previous bases: homology spaces
+! modulo the non-terminal domain surface, a.k.a the thin cuts.
+call gmsh%model%mesh%addHomologyRequest("Homology", domainTags=[domain_physical_tag], &
+                                        subdomainTags=[complement_physical_tag], &
+                                        dims=[0, 1, 2, 3])
+
+! Find cohomology space bases isomorphic to the previous bases: cohomology
+! spaces of the domain modulo the four terminals, a.k.a the thick cuts.
+call gmsh%model%mesh%addHomologyRequest("Cohomology", domainTags=[domain_physical_tag], &
+                                        subdomainTags=[terminals_physical_tag], &
+                                        dims=[0, 1, 2, 3])
+
+! more examples
+! call gmsh%model%mesh%addHomologyRequest()
+! call gmsh%model%mesh%addHomologyRequest("Homology", domainTags=[domain_physical_tag])
+! call gmsh%model%mesh%addHomologyRequest("Homology", domainTags=[domain_physical_tag], &
+!                                         subdomainTags=[boundary_physical_tag], &
+!                                         dims=[0,1,2,3])
+
+! Generate the mesh and perform the requested homology computations
+call gmsh%model%mesh%generate(3)
+
+! For more information, see M. Pellikka, S. Suuriniemi, L. Kettunen and
+! C. Geuzaine. Homology and cohomology computation in finite element
+! modeling. SIAM Journal on Scientific Computing 35(5), pp. 1195-1214, 2013.
+
+call gmsh%write("t14.msh")
+
+! Launch the GUI to see the results:
+call get_command(cmd)
+if (index(cmd, "-nopopup") == 0) call gmsh%fltk%run()
+
+call gmsh%finalize()
+
+end program t14
diff --git a/tutorials/fortran/t15.f90 b/tutorials/fortran/t15.f90
new file mode 100644
index 0000000000000000000000000000000000000000..09c77c46f038543dbdd56c8aa69f692366f42041
--- /dev/null
+++ b/tutorials/fortran/t15.f90
@@ -0,0 +1,113 @@
+! ------------------------------------------------------------------------------
+!
+!  Gmsh Fortran tutorial 15
+!
+!  Embedded points, lines and surfaces
+!
+! ------------------------------------------------------------------------------
+
+! By default, across geometrical dimensions meshes generated by Gmsh are only
+! conformal if lower dimensional entities are on the boundary of higher
+! dimensional ones (i.e. if points, curves or surfaces are part of the boundary
+! of volumes).
+
+! Embedding constraints allow to force a mesh to be conformal to other lower
+! dimensional entities.
+
+program t15
+
+use, intrinsic :: iso_c_binding
+use gmsh
+
+implicit none
+type(gmsh_t) :: gmsh
+integer(c_int) :: ret, p
+integer(c_int), allocatable :: tags(:,:)
+real(c_double) :: lc, l
+character(len=GMSH_API_MAX_STR_LEN) :: cmd
+
+call gmsh%initialize()
+
+! Copied from `t1.f90'...
+lc = 1e-2
+ret = gmsh%model%geo%addPoint(.0d0, .0d0, 0d0, lc, 1)
+ret = gmsh%model%geo%addPoint(.1d0, .0d0, 0d0, lc, 2)
+ret = gmsh%model%geo%addPoint(.1d0, .3d0, 0d0, lc, 3)
+ret = gmsh%model%geo%addPoint(.0d0, .3d0, 0d0, lc, 4)
+ret = gmsh%model%geo%addLine(1, 2, 1)
+ret = gmsh%model%geo%addLine(3, 2, 2)
+ret = gmsh%model%geo%addLine(3, 4, 3)
+ret = gmsh%model%geo%addLine(4, 1, 4)
+ret = gmsh%model%geo%addCurveLoop([4, 1, -2, 3], 1)
+ret = gmsh%model%geo%addPlaneSurface([1], 1)
+
+! We change the mesh size to generate a coarser mesh
+lc = lc * 4
+call gmsh%model%geo%mesh%setSize(reshape([0, 1, 0, 2, 0, 3, 0, 4], [2, 4]), lc)
+
+! We define a new point
+ret = gmsh%model%geo%addPoint(0.02d0, 0.02d0, 0.d0, lc, 5)
+
+! We have to synchronize before embedding entites:
+call gmsh%model%geo%synchronize()
+
+! One can force this point to be included ("embedded") in the 2D mesh, using the
+! `embed()' function:
+call gmsh%model%mesh%embed(0, [5], 2, 1)
+
+! In the same way, one can use `embed()' to force a curve to be embedded in the
+! 2D mesh:
+ret = gmsh%model%geo%addPoint(0.02d0, 0.12d0, 0.d0, lc, 6)
+ret = gmsh%model%geo%addPoint(0.04d0, 0.18d0, 0.d0, lc, 7)
+ret = gmsh%model%geo%addLine(6, 7, 5)
+
+call gmsh%model%geo%synchronize()
+call gmsh%model%mesh%embed(1, [5], 2, 1)
+
+! Points and curves can also be embedded in volumes
+call gmsh%model%geo%extrude(reshape([2, 1], [2, 1]), 0d0, 0d0, 0.1d0, tags)
+
+p = gmsh%model%geo%addPoint(0.07d0, 0.15d0, 0.025d0, lc)
+
+call gmsh%model%geo%synchronize()
+call gmsh%model%mesh%embed(0, [p], 3, 1)
+
+ret = gmsh%model%geo%addPoint(0.025d0, 0.15d0, 0.025d0, lc, p + 1)
+l = gmsh%model%geo%addLine(7, p + 1)
+
+call gmsh%model%geo%synchronize()
+call gmsh%model%mesh%embed(1, [int(l)], 3, 1)
+
+! Finally, we can also embed a surface in a volume:
+ret = gmsh%model%geo%addPoint(0.02d0, 0.12d0, 0.05d0, lc, p + 2)
+ret = gmsh%model%geo%addPoint(0.04d0, 0.12d0, 0.05d0, lc, p + 3)
+ret = gmsh%model%geo%addPoint(0.04d0, 0.18d0, 0.05d0, lc, p + 4)
+ret = gmsh%model%geo%addPoint(0.02d0, 0.18d0, 0.05d0, lc, p + 5)
+
+ret = gmsh%model%geo%addLine(p + 2, p + 3, int(l + 1))
+ret = gmsh%model%geo%addLine(p + 3, p + 4, int(l + 2))
+ret = gmsh%model%geo%addLine(p + 4, p + 5, int(l + 3))
+ret = gmsh%model%geo%addLine(p + 5, p + 2, int(l + 4))
+
+ret = gmsh%model%geo%addCurveLoop([int(l) + 1, int(l) + 2, int(l) + 3, int(l) + 4])
+ret = gmsh%model%geo%addPlaneSurface([ret])
+
+call gmsh%model%geo%synchronize()
+call gmsh%model%mesh%embed(2, [ret], 3, 1)
+
+! Note that with the OpenCASCADE kernel (see `t16.f90'), when the `fragment()'
+! function is applied to entities of different dimensions, the lower dimensional
+! entities will be autmatically embedded in the higher dimensional entities if
+! necessary.
+
+call gmsh%model%mesh%generate(3)
+
+call gmsh%write("t15.msh")
+
+! Launch the GUI to see the results:
+call get_command(cmd)
+if (index(cmd, "-nopopup") == 0) call gmsh%fltk%run()
+
+call gmsh%finalize()
+
+end program t15
diff --git a/tutorials/fortran/t16.f90 b/tutorials/fortran/t16.f90
new file mode 100644
index 0000000000000000000000000000000000000000..9f595a535adbe9063f9ff03f8627b29a10688b9c
--- /dev/null
+++ b/tutorials/fortran/t16.f90
@@ -0,0 +1,156 @@
+! ------------------------------------------------------------------------------
+!
+!  Gmsh Fortran tutorial 16
+!
+!  Constructive Solid Geometry, OpenCASCADE geometry kernel
+!
+! ------------------------------------------------------------------------------
+
+! Instead of constructing a model in a bottom-up fashion with Gmsh's built-in
+! geometry kernel, starting with version 3 Gmsh allows you to directly use
+! alternative geometry kernels. Here we will use the OpenCASCADE kernel.
+
+program t16
+
+use, intrinsic :: iso_c_binding
+use gmsh
+
+implicit none
+
+type(gmsh_t) :: gmsh
+integer(c_int) :: ret, p, t
+integer(c_int), allocatable :: ov(:,:), ovv(:,:), holes(:,:)
+integer(c_size_t), allocatable :: ovv_n(:)
+real(c_double) :: x, y, z, r, lcar1, lcar2, lcar3, eps
+character(len=GMSH_API_MAX_STR_LEN) :: cmd, str
+character(len=GMSH_API_MAX_STR_LEN), allocatable :: log(:)
+
+call gmsh%initialize()
+
+call gmsh%model%add("t16")
+
+! Let's build the same model as in `t5.f90', but using constructive solid
+! geometry.
+
+! We can log all messages for further processing with:
+call gmsh%logger%start()
+
+! We first create two cubes:
+ret = gmsh%model%occ%addBox(0.0d0, 0.0d0, 0.0d0, 1.0d0, 1.0d0, 1.0d0, 1)
+ret = gmsh%model%occ%addBox(0.0d0, 0.0d0, 0.0d0, 0.5d0, 0.5d0, 0.5d0, 2)
+
+! We apply a boolean difference to create the "cube minus one eigth" shape:
+call gmsh%model%occ%cut(objectDimTags=reshape([3, 1], [2, 1]), &
+                        toolDimTags=reshape([3, 2], [2, 1]), &
+                        outDimTags=ov, &
+                        outDimTagsMap=ovv, &
+                        outDimTagsMap_n=ovv_n, &
+                        tag=3)
+print*, "ovv_n =", ovv_n
+print*, "ovv =", ovv
+print*, "ov =", ov
+! stop
+deallocate(ov, ovv, ovv_n)
+
+! Boolean operations with OpenCASCADE always create new entities. By default the
+! extra arguments `removeObject' and `removeTool' in `cut()' are set to `True',
+! which will delete the original entities.
+
+! We then create the five spheres:
+x = 0
+y = 0.75
+z = 0
+r = 0.09
+holes = reshape([(3, 3 + t, t = 1, 5)], [1, 10])
+do t = 1, 5
+    x = x + 0.166
+    z = z + 0.166
+    ret = gmsh%model%occ%addSphere(xc=x, yc=y, zc=z, radius=r, tag=(3 + t))
+end do
+
+! If we had wanted five empty holes we would have used `cut()' again. Here we
+! want five spherical inclusions, whose mesh should be conformal with the mesh
+! of the cube: we thus use `fragment()', which intersects all volumes in a
+! conformal manner (without creating duplicate interfaces):
+call gmsh%model%occ%fragment(objectDimTags=reshape([3, 3], [2, 1]), &
+                             toolDimTags=holes, &
+                             outDimTags=ov, &
+                             outDimTagsMap=ovv, &
+                             outDimTagsMap_n=ovv_n)
+
+! ov contains all the generated entities of the same dimension as the input
+! entities:
+print*, "fragment produced volumes:"
+print'(A,g0,A,g0,A)', ('(', ov(1,t), ',', ov(2,t), ')', t = 1, size(ov, 2))
+
+! ovv contains the parent-child relationships for all the input entities:
+print*, "before/after fragment relations:"
+
+call gmsh%model%occ%synchronize()
+
+! When the boolean operation leads to simple modifications of entities, and if
+! one deletes the original entities, Gmsh tries to assign the same tag to the
+! new entities. (This behavior is governed by the
+! `Geometry.OCCBooleanPreserveNumbering' option.)
+
+! Here the `Physical Volume' definitions can thus be made for the 5 spheres
+! directly, as the five spheres (volumes 4, 5, 6, 7 and 8), which will be
+! deleted by the fragment operations, will be recreated identically (albeit with
+! new surfaces) with the same tags:
+do t = 1, 5
+    ret = gmsh%model%addPhysicalGroup(3, [3 + t], t)
+end do
+
+! The tag of the cube will change though, so we need to access it
+! programmatically:
+ret = gmsh%model%addPhysicalGroup(3, [ov(2, size(ov, 1))], 10)
+deallocate(ov, ovv, ovv_n)
+
+! Creating entities using constructive solid geometry is very powerful, but can
+! lead to practical issues for e.g. setting mesh sizes at points, or identifying
+! boundaries.
+
+! To identify points or other bounding entities you can take advantage of the
+! `getEntities()', `getBoundary()' and `getEntitiesInBoundingBox()' functions:
+
+lcar1 = .1
+lcar2 = .0005
+lcar3 = .055
+
+! Assign a mesh size to all the points:
+call gmsh%model%getEntities(ov, 0)
+call gmsh%model%mesh%setSize(ov, lcar1)
+deallocate(ov)
+
+! Override this constraint on the points of the five spheres:
+call gmsh%model%getBoundary(holes, ov, .false., .false., .true.)
+call gmsh%model%mesh%setSize(ov, lcar3)
+deallocate(ov)
+
+! Select the corner point by searching for it geometrically:
+eps = 1e-3
+call gmsh%model%getEntitiesInBoundingBox(0.5 - eps, 0.5 - eps, 0.5 - eps, &
+                                         0.5 + eps, 0.5 + eps, 0.5 + eps, ov, 0)
+call gmsh%model%mesh%setSize(ov, lcar2)
+
+call gmsh%model%mesh%generate(3)
+
+call gmsh%write("t16.msh")
+
+! Additional examples created with the OpenCASCADE geometry kernel are available
+! in `t18.f90', `t19.f90' and `t20.f90', as well as in the `examples/api'
+! directory.
+
+! Inspect the log:
+call gmsh%logger%get(log)
+write(str, '(A)') size(log)
+print*, "Logger has recorded "//trim(str)//" lines"
+call gmsh%logger%stop()
+
+! Launch the GUI to see the results:
+call get_command(cmd)
+if (index(cmd, "-nopopup") == 0) call gmsh%fltk%run()
+
+call gmsh%finalize()
+
+end program t16
diff --git a/tutorials/fortran/t17.f90 b/tutorials/fortran/t17.f90
new file mode 100644
index 0000000000000000000000000000000000000000..8c580ce93f78bfbc6f6f81b95295573faf4089e5
--- /dev/null
+++ b/tutorials/fortran/t17.f90
@@ -0,0 +1,57 @@
+! ------------------------------------------------------------------------------
+!
+!  Gmsh Fortran tutorial 17
+!
+!  Anisotropic background mesh
+!
+! ------------------------------------------------------------------------------
+
+! As seen in `t7.f90', mesh sizes can be specified very accurately by providing a
+! background mesh, i.e., a post-processing view that contains the target mesh
+! sizes.
+
+! Here, the background mesh is represented as a metric tensor field defined on a
+! square. One should use bamg as 2d mesh generator to enable anisotropic meshes
+! in 2D.
+program t17
+
+use, intrinsic :: iso_c_binding
+use gmsh
+
+implicit none
+
+type(gmsh_t) :: gmsh
+integer(c_int) :: bg_field, ret
+character(len=GMSH_API_MAX_STR_LEN) :: cmd
+
+call gmsh%initialize()
+
+call gmsh%model%add("t17")
+
+! Create a square
+ret = gmsh%model%occ%addRectangle(-2d0, -2d0, 0d0, 4d0, 4d0)
+call gmsh%model%occ%synchronize()
+
+! Merge a post-processing view containing the target anisotropic mesh sizes
+call gmsh%merge('../t17_bgmesh.pos')
+
+! Apply the view as the current background mesh
+bg_field = gmsh%model%mesh%field%add("PostView")
+call gmsh%model%mesh%field%setNumber(bg_field, "ViewIndex", 0d0)
+call gmsh%model%mesh%field%setAsBackgroundMesh(bg_field)
+
+! Use bamg
+call gmsh%option%setNumber("Mesh.SmoothRatio", 3d0)
+call gmsh%option%setNumber("Mesh.AnisoMax", 1000d0)
+call gmsh%option%setNumber("Mesh.Algorithm", 7d0)
+
+call gmsh%model%mesh%generate(2)
+call gmsh%write("t17.msh")
+
+! Launch the GUI to see the results:
+call get_command(cmd)
+if (index(cmd, "-nopopup") == 0) call gmsh%fltk%run()
+
+call gmsh%finalize()
+
+end program t17
diff --git a/tutorials/fortran/t18.f90 b/tutorials/fortran/t18.f90
new file mode 100644
index 0000000000000000000000000000000000000000..227037a74c3385d6043b11d942e7d16806454474
--- /dev/null
+++ b/tutorials/fortran/t18.f90
@@ -0,0 +1,158 @@
+! ------------------------------------------------------------------------------
+!
+!  Gmsh Fortran tutorial 18
+!
+!  Periodic meshes
+!
+! ------------------------------------------------------------------------------
+
+! Periodic meshing constraints can be imposed on surfaces and curves.
+
+program t18
+
+use, intrinsic :: iso_c_binding
+use gmsh
+
+implicit none
+
+type(gmsh_t) :: gmsh
+integer(c_int) :: ret, i, j
+integer(c_int), allocatable :: tags(:,:), out(:,:), out_map(:,:), p(:,:), sxmin(:,:), sxmax(:,:), tmp(:)
+integer(c_size_t), allocatable :: out_map_n(:)
+real(c_double), allocatable :: translation(:)
+real(c_double) :: xmin, ymin, zmin, xmax, ymax, zmax, xmin2, ymin2, zmin2, xmax2, ymax2, zmax2, x, y, z, eps
+character(len=GMSH_API_MAX_STR_LEN) :: cmd
+
+call gmsh%initialize()
+
+call gmsh%model%add("t18")
+
+! Let's use the OpenCASCADE geometry kernel to build two geometries.
+
+! The first geometry is very simple: a unit cube with a non-uniform mesh size
+! constraint (set on purpose to be able to verify visually that the periodicity
+! constraint works!):
+
+ret = gmsh%model%occ%addBox(0d0, 0d0, 0d0, 1d0, 1d0, 1d0, 1)
+call gmsh%model%occ%synchronize()
+
+call gmsh%model%getEntities(tags, 0)
+call gmsh%model%mesh%setSize(tags, 0.1d0)
+call gmsh%model%mesh%setSize(reshape([0, 1], [2, 1]), 0.02d0)
+deallocate(tags)
+
+! To impose that the mesh on surface 2 (the right side of the cube) should
+! match the mesh from surface 1 (the left side), the following periodicity
+! constraint is set:
+translation = [1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]
+call gmsh%model%mesh%setPeriodic(2, [2], [1], translation)
+
+! The periodicity transform is provided as a 4x4 affine transformation matrix,
+! given by row.
+
+! During mesh generation, the mesh on surface 2 will be created by copying
+! the mesh from surface 1.
+
+! Multiple periodicities can be imposed in the same way:
+call gmsh%model%mesh%setPeriodic(2, [6], [5], &
+                            [real(c_double) :: 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1])
+call gmsh%model%mesh%setPeriodic(2, [4], [3], &
+                            [real(c_double) :: 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1])
+
+! For more complicated cases, finding the corresponding surfaces by hand can
+! be tedious, especially when geometries are created through solid
+! modelling. Let's construct a slightly more complicated geometry.
+
+! We start with a cube and some spheres:
+ret = gmsh%model%occ%addBox(2d0, 0d0, 0d0, 1d0, 1d0, 1d0, 10)
+x = 2 - 0.3
+y = 0
+z = 0
+ret = gmsh%model%occ%addSphere(x, y, z, 0.35d0, 11)
+ret = gmsh%model%occ%addSphere(x + 1, y, z, 0.35d0, 12)
+ret = gmsh%model%occ%addSphere(x, y + 1, z, 0.35d0, 13)
+ret = gmsh%model%occ%addSphere(x, y, z + 1, 0.35d0, 14)
+ret = gmsh%model%occ%addSphere(x + 1, y + 1, z, 0.35d0, 15)
+ret = gmsh%model%occ%addSphere(x, y + 1, z + 1, 0.35d0, 16)
+ret = gmsh%model%occ%addSphere(x + 1, y, z + 1, 0.35d0, 17)
+ret = gmsh%model%occ%addSphere(x + 1, y + 1, z + 1, 0.35d0, 18)
+
+! We first fragment all the volumes, which will leave parts of spheres
+! protruding outside the cube:
+tags = reshape([(3, i, i = 11, 18)], [2, 19-11])
+call gmsh%model%occ%fragment(reshape([3, 10], [2, 1]), tags, &
+                             out, out_map, out_map_n)
+deallocate(tags, out_map, out_map_n)
+
+call gmsh%model%occ%synchronize()
+
+! Ask OpenCASCADE to compute more accurate bounding boxes of entities using
+! the STL mesh:
+call gmsh%option%setNumber("Geometry.OCCBoundsUseStl", 1d0)
+
+! We then retrieve all the volumes in the bounding box of the original cube,
+! and delete all the parts outside it:
+eps = 1e-3
+call gmsh%model%getEntitiesInBoundingBox(2 - eps, -eps, -eps, 2 + 1 + eps, &
+                                         1 + eps, 1 + eps, dim=3, tags=tags)
+
+tmp = pack(out, out /= tags)
+out = reshape(tmp, [2, size(tmp)/2])
+deallocate(tmp)
+
+call gmsh%model%removeEntities(out, .true.)  ! Delete outside parts recursively
+deallocate(out)
+
+! We now set a non-uniform mesh size constraint (again to check results
+! visually):
+call gmsh%model%getBoundary(tags, p, .false., .false., .true.)  ! Get all points
+call gmsh%model%mesh%setSize(p, 0.1d0)
+deallocate(p)
+
+call gmsh%model%getEntitiesInBoundingBox(2 - eps, -eps, -eps, 2 + eps, eps, eps,&
+                                         dim=0, tags=p)
+
+call gmsh%model%mesh%setSize(p, 0.001d0)
+
+! We now identify corresponding surfaces on the left and right sides of the
+! geometry automatically.
+
+! First we get all surfaces on the left:
+call gmsh%model%getEntitiesInBoundingBox(2 - eps, -eps, -eps, 2 + eps, &
+                                         1 + eps, 1 + eps, dim=2, tags=sxmin)
+
+do i = 1, size(sxmin, 2)
+    ! Then we get the bounding box of each left surface
+    call gmsh%model%getBoundingBox(sxmin(1,i), sxmin(2,i), xmin, ymin, zmin, xmax, ymax, zmax)
+    ! We translate the bounding box to the right and look for surfaces inside
+    ! it:
+    if (allocated(sxmax)) deallocate(sxmax)
+    call gmsh%model%getEntitiesInBoundingBox(xmin - eps + 1, ymin - eps, &
+                                             zmin - eps, xmax + eps + 1, &
+                                             ymax + eps, zmax + eps, dim=2, tags=sxmax)
+
+    ! For all the matches, we compare the corresponding bounding boxes...
+    do j = 1, size(sxmax, 2)
+        call gmsh%model%getBoundingBox( &
+            sxmax(1,j), sxmax(2,j), xmin2, ymin2, zmin2, xmax2, ymax2, zmax2)
+        xmin2 = xmin2 - 1
+        xmax2 = xmax2 - 1
+        ! ...and if they match, we apply the periodicity constraint
+        if (abs(xmin2 - xmin) < eps .and. abs(xmax2 - xmax) < eps &
+                .and. abs(ymin2 - ymin) < eps .and. abs(ymax2 - ymax) < eps &
+                .and. abs(zmin2 - zmin) < eps .and. abs(zmax2 - zmax) < eps) then
+            call gmsh%model%mesh%setPeriodic(2, [sxmax(2,j)], [sxmin(2,i)], translation)
+        end if
+    end do
+end do
+
+call gmsh%model%mesh%generate(3)
+call gmsh%write("t18.msh")
+
+! Launch the GUI to see the results:
+call get_command(cmd)
+if (index(cmd, "-nopopup") == 0) call gmsh%fltk%run()
+
+call gmsh%finalize()
+
+end program t18
diff --git a/tutorials/fortran/t19.f90 b/tutorials/fortran/t19.f90
new file mode 100644
index 0000000000000000000000000000000000000000..e241a8a43d459c3688f53dbd954e1373209c7b74
--- /dev/null
+++ b/tutorials/fortran/t19.f90
@@ -0,0 +1,112 @@
+! ------------------------------------------------------------------------------
+!
+!  Gmsh Fortran tutorial 19
+!
+!  Thrusections, fillets, pipes, mesh size from curvature
+!
+! ------------------------------------------------------------------------------
+
+! The OpenCASCADE geometry kernel supports several useful features for solid
+! modelling.
+
+program t19
+
+use, intrinsic :: iso_c_binding
+use gmsh
+
+implicit none
+
+type(gmsh_t) :: gmsh
+integer(c_int) :: ret, i, npts
+integer(c_int), allocatable :: tags(:,:), out(:,:), tmp(:,:), e(:,:), p(:)
+real(c_double) :: nturns, r, h, theta
+character(len=GMSH_API_MAX_STR_LEN) :: cmd
+
+
+call gmsh%initialize()
+
+call gmsh%model%add("t19")
+
+! Volumes can be constructed from (closed) curve loops thanks to the
+! `addThruSections()' function
+ret = gmsh%model%occ%addCircle(0d0, 0d0, 0d0, 0.5d0, 1)
+ret = gmsh%model%occ%addCurveLoop([1], 1)
+ret = gmsh%model%occ%addCircle(0.1d0, 0.05d0, 1d0, 0.1d0, 2)
+ret = gmsh%model%occ%addCurveLoop([2], 2)
+ret = gmsh%model%occ%addCircle(-0.1d0, -0.1d0, 2d0, 0.3d0, 3)
+ret = gmsh%model%occ%addCurveLoop([3], 3)
+call gmsh%model%occ%addThruSections([1, 2, 3], outdimtags=tags, tag=1)
+call gmsh%model%occ%synchronize()
+deallocate(tags)
+
+! We can also force the creation of ruled surfaces:
+ret = gmsh%model%occ%addCircle(2 + 0d0, 0d0, 0d0, 0.5d0, 11)
+ret = gmsh%model%occ%addCurveLoop([11], 11)
+ret = gmsh%model%occ%addCircle(2 + 0.1d0, 0.05d0, 1d0, 0.1d0, 12)
+ret = gmsh%model%occ%addCurveLoop([12], 12)
+ret = gmsh%model%occ%addCircle(2 - 0.1d0, -0.1d0, 2d0, 0.3d0, 13)
+ret = gmsh%model%occ%addCurveLoop([13], 13)
+call gmsh%model%occ%addThruSections([11, 12, 13], tags, 11, .true., .true.)
+call gmsh%model%occ%synchronize()
+deallocate(tags)
+
+! We copy the first volume, and fillet all its edges:
+call gmsh%model%occ%copy(reshape([3, 1], [2, 1]), out)
+call gmsh%model%occ%translate(out, 4d0, 0d0, 0d0)
+call gmsh%model%occ%synchronize()
+call gmsh%model%getBoundary(out, tags);
+call gmsh%model%getBoundary(tags, e, .false.)
+call gmsh%model%occ%fillet([out(2, 1)], abs(e(2,:)), [0.1d0], tmp); deallocate(tmp)
+call gmsh%model%occ%synchronize()
+
+! OpenCASCADE also allows general extrusions along a smooth path. Let's first
+! define a spline curve:
+nturns = 1.
+npts = 20
+r = 1.
+h = 1. * nturns
+p = [(1000 + i, i = 0, npts)]
+do i = 0, npts
+    theta = i * 2 * M_PI * nturns / npts
+    ret = gmsh%model%occ%addPoint(r * cos(theta), r * sin(theta), i * h / npts, 1d0, 1000 + i)
+end do
+ret = gmsh%model%occ%addSpline(p, 1000)
+
+! A wire is like a curve loop, but open:
+ret = gmsh%model%occ%addWire([1000], 1000)
+
+! We define the shape we would like to extrude along the spline (a disk):
+ret = gmsh%model%occ%addDisk(1d0, 0d0, 0d0, 0.2d0, 0.2d0, 1000)
+call gmsh%model%occ%rotate(reshape([2, 1000], [2, 1]), 0d0, 0d0, 0d0, 1d0, 0d0, 0d0, M_PI / 2)
+
+! We extrude the disk along the spline to create a pipe (other sweeping types
+! can be specified; try e.g. 'Frenet' instead of 'DiscreteTrihedron'):
+call gmsh%model%occ%addPipe(reshape([2, 1000], [2, 1]), 1000, out, 'DiscreteTrihedron')
+deallocate(out)
+
+! We delete the source surface, and increase the number of sub-edges for a
+! nicer display of the geometry:
+call gmsh%model%occ%remove(reshape([2, 1000], [2, 1]))
+call gmsh%option%setNumber("Geometry.NumSubEdges", 1000d0)
+
+call gmsh%model%occ%synchronize()
+
+! We can activate the calculation of mesh element sizes based on curvature
+! (here with a target of 20 elements per 2*Pi radians):
+call gmsh%option%setNumber("Mesh.MeshSizeFromCurvature", 20d0)
+
+! We can constraint the min and max element sizes to stay within reasonnable
+! values (see `t10.f90' for more details):
+call gmsh%option%setNumber("Mesh.MeshSizeMin", 0.001d0)
+call gmsh%option%setNumber("Mesh.MeshSizeMax", 0.3d0)
+
+call gmsh%model%mesh%generate(3)
+call gmsh%write("t19.msh")
+
+! Launch the GUI to see the results:
+call get_command(cmd)
+if (index(cmd, "-nopopup") == 0) call gmsh%fltk%run()
+
+call gmsh%finalize()
+
+end program t19
diff --git a/tutorials/fortran/t2.f b/tutorials/fortran/t2.f
deleted file mode 100644
index 98457e5e8d64258590741257e08ca3f0d7ea7203..0000000000000000000000000000000000000000
--- a/tutorials/fortran/t2.f
+++ /dev/null
@@ -1,193 +0,0 @@
-c ---------------------------------------------------------------------------
-c
-c   Gmsh Fortran tutorial 2
-c
-c   Transformations, extruded geometries, volumes
-c
-c ---------------------------------------------------------------------------
-
-      include "gmshf.h"
-
-      program main
-      use, intrinsic :: iso_c_binding
-      use gmsh_fortran
-
-      implicit none
-      integer(c_int) :: ierr, argc, itmp, i, ps, status, len
-      integer(c_int) :: recombine
-      integer(c_size_t) :: ov_n, xyz_n, numElements_n, heights_n, ov2_n
-      real(c_double) :: lc
-
-      integer(c_int) :: cl1(4) = (/4, 1, -2, 3/)
-      integer(c_int) :: cl2(4) = (/5, -8, -7, 3/)
-      integer(c_int) :: cl3(4) = (/115, -111, 3, 110/)
-      integer(c_int) :: cl4(4) = (/111, 116, -112, -7/)
-      integer(c_int) :: cl5(4) = (/112, 117, -113, -8/)
-      integer(c_int) :: cl6(4) = (/114, -110, 5, 113/)
-      integer(c_int) :: cl7(4) = (/115, 116, 117, 114/)
-      integer(c_int) :: s1(1) = (/1/)
-      integer(c_int) :: s2(1) = (/10/)
-      integer(c_int) :: s3(1) = (/118/)
-      integer(c_int) :: s4(1) = (/120/)
-      integer(c_int) :: s5(1) = (/122/)
-      integer(c_int) :: s6(1) = (/124/)
-      integer(c_int) :: s7(1) = (/126/)
-      integer(c_int) :: g5(3) = (/1, 2, 4/)
-      integer(c_int) :: g6(1) = (/1/)
-      integer(c_int) :: g7(2) = (/129, 130/)
-      integer(c_int) :: t(2) = (/0, 5/)
-      integer(c_int) :: iv(2) = (/0, 3/)
-      integer(c_int) :: iv2(4) = (/2, 1, 2, 11/)
-      integer(c_int) :: numElements(0)
-      real (c_double) :: iv0(0)
-      real(c_double) :: heights(0)
-      integer(c_int) :: sl1(6) = (/127, 119, 121, 123, 125, 11/)
-      integer(c_int) :: v1(1) = (/128/)
-      integer(c_int) :: ss(16) =
-     &  (/0, 103, 0, 105, 0, 109, 0, 102, 0, 28, 0, 24, 0, 6, 0, 5/)
-
-      type(c_ptr), allocatable :: argv(:)
-      type(c_ptr) :: ov, xyz, ov2, ov_3
-
-      type string
-        character(len = :, kind = c_char), allocatable :: item
-      end type string
-      type(string), allocatable, target :: tmp(:)
-
-      character(80) :: buf
-
-      integer(c_int), pointer :: pf_ov(:), pf_ov3(:), pf_ov2(:)
-      real(c_double), pointer :: pf_xyz(:)
-
-      lc = 1d - 2
-
-      argc = command_argument_count()
-      allocate(argv(argc + 2))
-      allocate(tmp(argc + 1))
-
-      do i = 0, argc
-        call get_command_argument(i, buf, len)
-        tmp(i + 1) % item = buf(1 : len) // c_null_char
-        argv(i + 1) = c_loc(tmp(i + 1) % item)
-      enddo
-      argv(argc + 2) = c_null_ptr
-
-      call gmshInitialize(argc + 1, argv, 1, 0, ierr)
-
-      call gmshModelAdd("t2" // c_null_char, ierr)
-
-      itmp = gmshModelGeoAddPoint(0d0, 0d0, 0d0, lc, 1, ierr)
-      itmp = gmshModelGeoAddPoint(0.1d0, 0d0, 0d0, lc, 2, ierr)
-      itmp = gmshModelGeoAddPoint(0.1d0, 0.3d0, 0d0, lc, 3, ierr)
-      itmp = gmshModelGeoAddPoint(0d0, 0.3d0, 0d0, lc, 4, ierr)
-
-      itmp = gmshModelGeoAddLine(1, 2, 1, ierr)
-      itmp = gmshModelGeoAddLine(3, 2, 2, ierr)
-      itmp = gmshModelGeoAddLine(3, 4, 3, ierr)
-      itmp = gmshModelGeoAddLine(4, 1, 4, ierr)
-
-      itmp = gmshModelGeoAddCurveLoop(cl1, 4_8, 1, 0, ierr)
-      itmp = gmshModelGeoAddPlaneSurface(s1, 1_8, 1, ierr)
-
-      call gmshModelGeoSynchronize(ierr)
-      itmp = gmshModelAddPhysicalGroup(1, g5, 3_8, 5, ierr)
-      ps = gmshModelAddPhysicalGroup(2, g6, 1_8, -1, ierr)
-      call gmshModelSetPhysicalName(2, ps, "My surface" // c_null_char,
-     &     ierr)
-
-      itmp = gmshModelGeoAddPoint(0d0, 0.4d0, 0d0, lc, 5, ierr)
-
-      itmp = gmshModelGeoAddLine(4, 5, 5, ierr)
-
-      call gmshModelGeoTranslate(t, 2_8, -0.02d0, 0d0, 0d0, ierr)
-
-      call gmshModelGeoRotate(t, 2_8, 0d0, 0.3d0, 0d0, 0d0, 0d0, 1d0,
-     &                        -M_PI / 4d0, ierr)
-
-      call gmshModelGeoCopy(iv, 2_8, ov, ov_n, ierr)
-
-      call c_f_pointer(ov, pf_ov, [ov_n])
-      call gmshModelGeoTranslate(pf_ov, ov_n, 0d0, 0.05d0, 0d0, ierr)
-
-      itmp = gmshModelGeoAddLine(3, pf_ov(2), 7, ierr)
-      itmp = gmshModelGeoAddLine(pf_ov(2), 5, 8, ierr)
-
-      itmp = gmshModelGeoAddCurveLoop(cl2, 4_8, 10, 0, ierr)
-      itmp = gmshModelGeoAddPlaneSurface(s2, 1_8, 11, ierr)
-
-      call gmshModelGeoCopy(iv2, 4_8, ov, ov_n, ierr)
-
-      call c_f_pointer(ov, pf_ov, [ov_n])
-      call gmshModelGeoTranslate(pf_ov, ov_n, 0.12d0, 0d0, 0d0, ierr)
-
-      print *, "New surfaces ", pf_ov(2), " and ", pf_ov(4)
-
-      itmp = gmshModelGeoAddPoint(0d0, 0.3d0, 0.12d0, lc, 100, ierr)
-      itmp = gmshModelGeoAddPoint(0.1d0, 0.3d0, 0.12d0, lc, 101, ierr)
-      itmp = gmshModelGeoAddPoint(0.1d0, 0.35d0, 0.12d0, lc, 102, ierr)
-
-      call gmshModelGeoSynchronize(ierr)
-
-      call gmshModelGetValue(0, 5, iv0, 0_8, xyz, xyz_n, ierr)
-
-      call c_f_pointer(xyz, pf_xyz, [xyz_n])
-      itmp = gmshModelGeoAddPoint(pf_xyz(1), pf_xyz(2), 0.12d0, lc, 103, 
-     &                            ierr)
-
-      itmp = gmshModelGeoAddLine(4, 100, 110, ierr)
-      itmp = gmshModelGeoAddLine(3, 101, 111, ierr)
-      itmp = gmshModelGeoAddLine(6, 102, 112, ierr);
-      itmp = gmshModelGeoAddLine(5, 103, 113, ierr)
-      itmp = gmshModelGeoAddLine(103, 100, 114, ierr)
-      itmp = gmshModelGeoAddLine(100, 101, 115, ierr)
-      itmp = gmshModelGeoAddLine(101, 102, 116, ierr)
-      itmp = gmshModelGeoAddLine(102, 103, 117, ierr)
-
-      itmp = gmshModelGeoAddCurveLoop(cl3, 4_8, 118, 0, ierr)
-      itmp = gmshModelGeoAddPlaneSurface(s3, 1_8, 119, ierr)
-
-      itmp = gmshModelGeoAddCurveLoop(cl4, 4_8, 120, 0, ierr)
-      itmp = gmshModelGeoAddPlaneSurface(s4, 1_8, 121, ierr)
-
-      itmp = gmshModelGeoAddCurveLoop(cl5, 4_8, 122, 0, ierr)
-      itmp = gmshModelGeoAddPlaneSurface(s5, 1_8, 123, ierr)
-
-      itmp = gmshModelGeoAddCurveLoop(cl6, 4_8, 124, 0, ierr)
-      itmp = gmshModelGeoAddPlaneSurface(s6, 1_8, 125, ierr)
-
-      itmp = gmshModelGeoAddCurveLoop(cl7, 4_8, 126, 0, ierr)
-      itmp = gmshModelGeoAddPlaneSurface(s7, 1_8, 127, ierr)
-
-      itmp = gmshModelGeoAddSurfaceLoop(sl1, 6_8, 128, ierr)
-      itmp = gmshModelGeoAddVolume(v1, 1_8, 129, ierr)
-
-      numElements_n = 0
-      heights_n = 0
-      recombine=0
-      ov_3 = c_loc(pf_ov(3))
-      call c_f_pointer(ov_3, pf_ov3, [ov_n - 2])
-      call gmshModelGeoExtrude(pf_ov3, 2_8, 0d0, 0d0, 0.12d0,
-     &                 ov2, ov2_n, numElements, numElements_n,
-     &                 heights, heights_n, recombine, ierr)
-
-      call gmshModelGeoMeshSetSize(ss, 16_8, lc * 3, ierr)
-
-      call gmshModelGeoSynchronize(ierr)
-
-      itmp = gmshModelAddPhysicalGroup(3, g7, 2_8, 1, ierr)
-
-      call gmshModelSetPhysicalName(3, 1, "The volume" // c_null_char,
-     &     ierr)
-
-      call gmshModelMeshGenerate(3, ierr)
-      call gmshWrite("t2.msh" // c_null_char, ierr)
-
-c     call gmshFltkRun(ierr)
-
-      call gmshFinalize(ierr)
-
-      deallocate(tmp)
-      deallocate(argv)
-
-      stop
-      end
diff --git a/tutorials/fortran/t2.f90 b/tutorials/fortran/t2.f90
new file mode 100644
index 0000000000000000000000000000000000000000..057d1157b7827c1507271374aa3b6cbdfc98a935
--- /dev/null
+++ b/tutorials/fortran/t2.f90
@@ -0,0 +1,179 @@
+! ---------------------------------------------------------------------------
+!
+!   Gmsh Fortran tutorial 2
+!
+!   Transformations, extruded geometries, volumes
+!
+! ---------------------------------------------------------------------------
+
+
+program t2
+use, intrinsic :: iso_c_binding
+use gmsh
+
+implicit none
+type(gmsh_t) :: gmsh
+integer(c_int) :: t(2,1), ss(2,8), r, i
+real (c_double) :: lc
+integer(c_int), allocatable :: ov(:,:), ov2(:,:)
+character(len=GMSH_API_MAX_STR_LEN), allocatable :: argv(:)
+real(c_double), allocatable :: xyz(:)
+
+allocate(argv(command_argument_count() + 1))
+do i = 0, size(argv) - 1
+    call get_command_argument(i, argv(i+1))
+    argv(i+1) = trim(argv(i+1))
+end do
+call gmsh%initialize(argv)
+
+call gmsh%model%add("t2")
+
+! Copied from `t1.f90'...
+lc = 0.01
+r = gmsh%model%geo%addPoint(0.0d0, 0.0d0, 0.0d0, lc, 1)
+r = gmsh%model%geo%addPoint(0.1d0, 0.0d0, 0.0d0, lc, 2)
+r = gmsh%model%geo%addPoint(0.1d0, 0.3d0, 0.0d0, lc, 3)
+r = gmsh%model%geo%addPoint(0.0d0, 0.3d0, 0.0d0, lc, 4)
+r = gmsh%model%geo%addLine(1, 2, 1)
+r = gmsh%model%geo%addLine(3, 2, 2)
+r = gmsh%model%geo%addLine(3, 4, 3)
+r = gmsh%model%geo%addLine(4, 1, 4)
+r = gmsh%model%geo%addCurveLoop([4, 1, -2, 3], 1)
+r = gmsh%model%geo%addPlaneSurface([1], 1)
+call gmsh%model%geo%synchronize()
+r = gmsh%model%addPhysicalGroup(1, [1, 2, 4], 5)
+r = gmsh%model%addPhysicalGroup(2, [1], -1, "My surface")
+
+! We can then add new points and curves in the same way as we did in `t1.f90':
+r = gmsh%model%geo%addPoint(0.0d0, 0.4d0, 0.0d0, lc, 5)
+r = gmsh%model%geo%addLine(4, 5, 5)
+
+t = reshape([0, 5], shape(t))
+! But Gmsh also provides tools to transform (translate, rotate, etc.)
+! elementary entities or copies of elementary entities.  Geometrical
+! transformations take a vector of pairs of integers as first argument, which
+! contains the list of entities, represented by (dimension, tag) pairs.  For
+! example, the point 5 (dimension=0, tag=5) can be moved by 0.02 to the left
+! (dx=-0.02, dy=0, dz=0) with
+call gmsh%model%geo%translate(t, -0.02d0, 0.0d0, 0.0d0)
+
+! And it can be further rotated by -Pi/4 around (0, 0.3, 0) (with the rotation
+! along the z axis) with:
+call gmsh%model%geo%rotate(t, 0.0d0, 0.3d0, 0.0d0, 0.0d0, 0.0d0, 1.0d0, -acos(1.0d0) / 4.0d0)
+
+! Note that there are no units in Gmsh: coordinates are just numbers - it's
+! up to the user to associate a meaning to them.
+
+! Point 3 can be duplicated and translated by 0.05 along the y axis by using
+! the `copy()' function, which takes a vector of (dim, tag) pairs as input,
+! and returns another vector of (dim, tag) pairs:
+call gmsh%model%geo%copy(reshape([0, 3], [2, 1]), ov)
+call gmsh%model%geo%translate(ov, 0.0d0, 0.05d0, 0.0d0)
+
+! The new point tag is available in ov[0].second, and can be used to create
+! new lines:
+r = gmsh%model%geo%addLine(3, ov(2,1), 7)
+r = gmsh%model%geo%addLine(ov(2,1), 5, 8)
+r = gmsh%model%geo%addCurveLoop([5, -8, -7, 3], 10)
+r = gmsh%model%geo%addPlaneSurface([10], 11)
+
+! In the same way, we can translate copies of the two surfaces 1 and 11 to
+! the right with the following command:
+deallocate(ov)
+call gmsh%model%geo%copy(reshape([2, 1, 2, 11], [2, 2]), ov)
+call gmsh%model%geo%translate(ov, 0.12d0, 0d0, 0d0)
+
+print *, "New surfaces ", ov(2,1), " and ", ov(2,2)
+
+! Volumes are the fourth type of elementary entities in Gmsh. In the same way
+! one defines curve loops to build surfaces, one has to define surface loops
+! (i.e. `shells') to build volumes. The following volume does not have holes
+! and thus consists of a single surface loop:
+r = gmsh%model%geo%addPoint(0.0d0, 0.30d0, 0.12d0, lc, 100)
+r = gmsh%model%geo%addPoint(0.1d0, 0.30d0, 0.12d0, lc, 101)
+r = gmsh%model%geo%addPoint(0.1d0, 0.35d0, 0.12d0, lc, 102)
+
+! We would like to retrieve the coordinates of point 5 to create point 103,
+! so we synchronize the model, and use `getValue()'
+call gmsh%model%geo%synchronize()
+call gmsh%model%getValue(0, 5, [real(c_double)::], xyz)
+r = gmsh%model%geo%addPoint(xyz(1), xyz(2), 0.12d0, lc, 103)
+
+r = gmsh%model%geo%addLine(4, 100, 110)
+r = gmsh%model%geo%addLine(3, 101, 111)
+r = gmsh%model%geo%addLine(6, 102, 112)
+r = gmsh%model%geo%addLine(5, 103, 113)
+r = gmsh%model%geo%addLine(103, 100, 114)
+r = gmsh%model%geo%addLine(100, 101, 115)
+r = gmsh%model%geo%addLine(101, 102, 116)
+r = gmsh%model%geo%addLine(102, 103, 117)
+
+r = gmsh%model%geo%addCurveLoop([115, -111, 3, 110], 118)
+r = gmsh%model%geo%addPlaneSurface([118], 119)
+r = gmsh%model%geo%addCurveLoop([111, 116, -112, -7], 120)
+r = gmsh%model%geo%addPlaneSurface([120], 121)
+r = gmsh%model%geo%addCurveLoop([112, 117, -113, -8], 122)
+r = gmsh%model%geo%addPlaneSurface([122], 123)
+r = gmsh%model%geo%addCurveLoop([114, -110, 5, 113], 124)
+r = gmsh%model%geo%addPlaneSurface([124], 125)
+r = gmsh%model%geo%addCurveLoop([115, 116, 117, 114], 126)
+r = gmsh%model%geo%addPlaneSurface([126], 127)
+
+r = gmsh%model%geo%addSurfaceLoop([127, 119, 121, 123, 125, 11], 128)
+r = gmsh%model%geo%addVolume([128], 129)
+
+! When a volume can be extruded from a surface, it is usually easier to use the
+! `extrude()' function directly instead of creating all the points, curves and
+! surfaces by hand. For example, the following command extrudes the surface 11
+! along the z axis and automatically creates a new volume (as well as all the
+! needed points, curves and surfaces). As expected, the function takes a vector
+! of (dim, tag) pairs as input as well as the translation vector, and returns a
+! vector of (dim, tag) pairs as output:
+call gmsh%model%geo%extrude(reshape(ov(:,2), [2,1]), 0.0d0, 0.0d0, 0.12d0, ov2)
+
+! Mesh sizes associated to geometrical points can be set by passing a vector of
+! (dim, tag) pairs for the corresponding points:
+ss = reshape([0, 103, 0, 105, 0, 109, 0, 102, 0, 28, 0, 24, 0, 6, 0, 5], shape(ss))
+call gmsh%model%geo%mesh%setSize(ss, lc * 3)
+
+! We finish by synchronizing the data from the built-in CAD kernel with the Gmsh
+! model:
+call gmsh%model%geo%synchronize()
+
+! We group volumes 129 and 130 in a single physical group with tag `1' and
+! name "The volume":
+r = gmsh%model%addPhysicalGroup(3, [129, 130], 1, "The volume")
+
+! call gmsh%model%setPhysicalName(3, 1, "The volume")
+! We finally generate and save the mesh:
+call gmsh%model%mesh%generate(3)
+call gmsh%write("t2.msh")
+
+! Note that, if the transformation tools are handy to create complex geometries,
+! it is also sometimes useful to generate the `flat' geometry, with an explicit
+! representation of all the elementary entities.
+!
+! With the built-in CAD kernel, this can be achieved by saving the model in the
+! `Gmsh Unrolled GEO' format:
+!
+! call gmsh%write("t2.geo_unrolled");
+!
+! With the OpenCASCADE CAD kernel, unrolling the geometry can be achieved by
+! exporting in the `OpenCASCADE BRep' format:
+!
+! call gmsh%write("t2.brep");
+!
+! (OpenCASCADE geometries can also be exported as STEP files.)
+
+! It is important to note that Gmsh never translates geometry data into a common
+! representation: all the operations on a geometrical entity are performed
+! natively with the associated CAD kernel. Consequently, one cannot export a
+! geometry constructed with the built-in kernel as an OpenCASCADE BRep file; or
+! export an OpenCASCADE model as an Unrolled GEO file.
+
+! Launch the GUI to see the results:
+if (.not. any(argv == "-nopopup")) call gmsh%fltk%run()
+call gmsh%finalize()
+deallocate(ov, ov2, argv, xyz)
+
+end program t2
diff --git a/tutorials/fortran/t20.f90 b/tutorials/fortran/t20.f90
new file mode 100644
index 0000000000000000000000000000000000000000..e0e1f986b75cd58542dea5bebe8c4f15e79d7fff
--- /dev/null
+++ b/tutorials/fortran/t20.f90
@@ -0,0 +1,137 @@
+! ------------------------------------------------------------------------------
+!
+!  Gmsh Fortran tutorial 20
+!
+!  STEP import and manipulation, geometry partitioning
+!
+! ------------------------------------------------------------------------------
+
+! The OpenCASCADE CAD kernel allows to import STEP files and to modify them. In
+! this tutorial we will load a STEP geometry and partition it into slices.
+
+program t20
+
+use, intrinsic :: iso_c_binding
+use gmsh
+
+implicit none
+
+type(gmsh_t) :: gmsh
+integer(c_int) :: i, n
+integer(c_int), allocatable :: rm(:), tags(:,:), s(:,:), dels(:,:), v(:,:), tmp(:,:), tmp_map(:,:)
+integer(c_size_t), allocatable :: tmp_map_n(:)
+real(c_double) :: h, tx, ty, tz, eps
+real(c_double) :: xmin, ymin, zmin, xmax, ymax, zmax, dx, dy, dz, L, xx, yy, zz
+character(len=GMSH_API_MAX_STR_LEN) :: cmd, dir
+logical :: surf
+
+call gmsh%initialize()
+
+call gmsh%model%add("t20")
+
+! Load a STEP file (using `importShapes' instead of `merge' allows to directly
+! retrieve the tags of the highest dimensional imported entities):
+call gmsh%model%occ%importShapes('../t20_data.step', v)
+
+! If we had specified
+!
+! call gmsh%option%setString('Geometry.OCCTargetUnit', 'M')
+!
+! before merging the STEP file, OpenCASCADE would have converted the units to
+! meters (instead of the default, which is millimeters).
+
+! Get the bounding box of the volume:
+call gmsh%model%occ%getBoundingBox(v(1,1), v(2,1), xmin, ymin, zmin, xmax, ymax, zmax)
+
+! We want to slice the model into N slices, and either keep the volume slices
+! or just the surfaces obtained by the cutting:
+
+N = 5  ! Number of slices
+dir = 'X' ! Direction: 'X', 'Y' or 'Z'
+surf = .false.  ! Keep only surfaces?
+
+dx = (xmax - xmin)
+dy = (ymax - ymin)
+dz = (zmax - zmin)
+L = dz; if (trim(dir) /= 'X') L = dx
+H = dz; if (trim(dir) /= 'X') L = dy
+
+! Create the first cutting plane:
+s = reshape([2, gmsh%model%occ%addRectangle(xmin, ymin, zmin, L, H)], [2, 1])
+
+if (trim(dir) == 'X') then
+    call gmsh%model%occ%rotate(s, xmin, ymin, zmin, 0d0, 1d0, 0d0, -M_PI/2)
+else if (trim(dir) == 'Y') then
+    call gmsh%model%occ%rotate(s, xmin, ymin, zmin, 1d0, 0d0, 0d0, M_PI/2)
+end if
+tx = dx / N; if (dir /= 'X') tx = 0
+ty = dy / N; if (dir /= 'Y') ty = 0
+tz = dz / N; if (dir /= 'Z') tz = 0
+call gmsh%model%occ%translate(s, tx, ty, tz)
+
+! Create the other cutting planes:
+do i = 1, N-2
+    call gmsh%model%occ%copy(reshape(s(:, 1), [2, 1]), tags)
+    s = reshape([s, tags], [2, size(s, 2) + size(tags, 2)])
+    call gmsh%model%occ%translate(reshape(s(:,size(s,2)), [2,1]), i * tx, i * ty, i * tz)
+    deallocate(tags)
+end do
+
+! Fragment (i.e. intersect) the volume with all the cutting planes:
+call gmsh%model%occ%fragment(v, s, tmp, tmp_map, tmp_map_n)
+deallocate(tmp, tmp_map, tmp_map_n)
+
+! Now remove all the surfaces (and their bounding entities) that are not on the
+! boundary of a volume, i.e. the parts of the cutting planes that "stick out" of
+! the volume:
+call gmsh%model%occ%getEntities(tags, 2)
+call gmsh%model%occ%remove(tags, .true.); deallocate(tags)
+
+call gmsh%model%occ%synchronize()
+
+if (surf) then
+    ! If we want to only keep the surfaces, retrieve the surfaces in bounding
+    ! boxes around the cutting planes...
+    eps = 1e-4
+    if (allocated(s)) deallocate(s)
+    s = reshape([integer(c_int) ::], [2,0])
+    do i = 1, N-1
+        xx = xmin; if (dir /= 'X') xx = xmax
+        yy = ymin; if (dir /= 'Y') yy = ymax
+        zz = zmin; if (dir /= 'Z') zz = zmax
+        call gmsh%model%getEntitiesInBoundingBox( &
+            xmin - eps + i * tx, ymin - eps + i * ty, zmin - eps + i * tz, &
+            xx + eps + i * tx, yy + eps + i * ty, zz + eps + i * tz, tags, 2)
+        s = reshape([s, tags], [2, size(s,2) + size(tags,2)])
+    end do
+    ! ...and remove all the other entities (here directly in the model, as we
+    ! won't modify any OpenCASCADE entities later on):
+    call gmsh%model%getEntities(dels, 2)
+    ! This removal is not entirely accurate, it misses the 1-6 tuple values
+    ! but it works good enough for this example:
+    rm = pack(dels, dels /= s)
+    dels = reshape(rm, [2, size(rm)/2])
+
+    if (allocated(tmp)) deallocate(tmp)
+    call gmsh%model%getEntities(tmp, 3)
+    call gmsh%model%removeEntities(tmp); deallocate(tmp)
+    call gmsh%model%removeEntities(dels); deallocate(dels)
+    call gmsh%model%getEntities(tmp, 1)
+    call gmsh%model%removeEntities(tmp); deallocate(tmp)
+    call gmsh%model%getEntities(tmp, 0)
+    call gmsh%model%removeEntities(tmp); deallocate(tmp)
+end if
+
+! Finally, let's specify a global mesh size and mesh the partitioned model:
+call gmsh%option%setNumber("Mesh.MeshSizeMin", 3d0)
+call gmsh%option%setNumber("Mesh.MeshSizeMax", 3d0)
+call gmsh%model%mesh%generate(3)
+call gmsh%write("t20.msh")
+
+! Launch the GUI to see the results:
+call get_command(cmd)
+if (index(cmd, "-nopopup") == 0) call gmsh%fltk%run()
+
+call gmsh%finalize()
+
+end program t20
diff --git a/tutorials/fortran/t21.f90 b/tutorials/fortran/t21.f90
new file mode 100644
index 0000000000000000000000000000000000000000..550eaec7e5b42e2368f0deddcf43df15b6252d00
--- /dev/null
+++ b/tutorials/fortran/t21.f90
@@ -0,0 +1,199 @@
+! ------------------------------------------------------------------------------
+!
+!  Gmsh Fortran tutorial 21
+!
+!  Mesh partitioning
+!
+! ------------------------------------------------------------------------------
+
+! Gmsh can partition meshes using different algorithms, e.g. the graph
+! partitioner Metis or the `SimplePartition' plugin. For all the partitioning
+! algorithms, the relationship between mesh elements and mesh partitions is
+! encoded through the creation of new (discrete) elementary entities, called
+! "partition entities".
+!
+! Partition entities behave exactly like other discrete elementary entities; the
+! only difference is that they keep track of both a mesh partition index and
+! their parent elementary entity.
+!
+! The major advantage of this approach is that it allows to maintain a full
+! boundary representation of the partition entities, which Gmsh creates
+! automatically if `Mesh.PartitionCreateTopology' is set.
+
+program t21
+
+use, intrinsic :: iso_c_binding
+use gmsh
+
+implicit none
+
+type(gmsh_t) :: gmsh
+integer(c_int) :: ret
+integer(c_int), allocatable :: tags(:,:), tags_map(:,:)
+integer(c_size_t), allocatable :: tags_map_n(:)
+character(len=GMSH_API_MAX_STR_LEN) :: cmd
+
+
+call gmsh%initialize()
+
+! Let us start by creating a simple geometry with two adjacent squares sharing
+! an edge:
+call gmsh%model%add("t21")
+ret = gmsh%model%occ%addRectangle(0d0, 0d0, 0d0, 1d0, 1d0, 1)
+ret = gmsh%model%occ%addRectangle(1d0, 0d0, 0d0, 1d0, 1d0, 2)
+call gmsh%model%occ%fragment(reshape([2, 1], [2, 1]), reshape([2, 2], [2, 1]), tags, tags_map, tags_map_n)
+call gmsh%model%occ%synchronize()
+call gmsh%model%getEntities(tags, 0)
+call gmsh%model%mesh%setSize(tags, 0.05d0)
+
+! We create one physical group for each square, and we mesh the resulting
+! geometry:
+ret = gmsh%model%addPhysicalGroup(2, [1], 100, "Left")
+ret = gmsh%model%addPhysicalGroup(2, [2], 200, "Right")
+call gmsh%model%mesh%generate(2)
+
+! We now define several ONELAB parameters to fine-tune how the mesh will be
+! partitioned:
+call gmsh%onelab%set('['//&
+  '{'//&
+    '"type":"number",'//&
+    '"name":"Parameters/0Mesh partitioner",'//&
+    '"values":[0],'//&
+    '"choices":[0, 1],'//&
+    '"valueLabels":{"Metis":0, "SimplePartition":1}'//&
+  '},'//&
+  '{'//&
+    '"type":"number",'//&
+    '"name":"Parameters/1Number of partitions",'//&
+    '"values":[3],'//&
+    '"min":1,'//&
+    '"max":256,'//&
+    '"step":1'//&
+  '},'//&
+  '{'//&
+    '"type":"number",'//&
+    '"name":"Parameters/2Create partition topology (BRep)?",'//&
+    '"values":[1],'//&
+    '"choices":[0, 1]'//&
+  '},'//&
+  '{'//&
+    '"type":"number",'//&
+    '"name":"Parameters/3Create ghost cells?",'//&
+    '"values":[0],'//&
+    '"choices":[0, 1]'//&
+  '},'//&
+  '{'//&
+    '"type":"number",'//&
+    '"name":"Parameters/3Create new physical groups?",'//&
+    '"values":[0],'//&
+    '"choices":[0, 1]'//&
+  '},'//&
+  '{'//&
+    '"type":"number",'//&
+    '"name":"Parameters/3Write file to disk?",'//&
+    '"values":[1],'//&
+    '"choices":[0, 1]'//&
+  '},'//&
+  '{'//&
+    '"type":"number",'//&
+    '"name":"Parameters/4Write one file per partition?",'//&
+    '"values":[0],'//&
+    '"choices":[0, 1]'//&
+  '}'//&
+']')
+
+call partitionMesh()
+
+call get_command(cmd)
+if (index(cmd, "-nopopup") == 0) then
+    call gmsh%fltk%initialize()
+    do while (transfer(gmsh%fltk%isAvailable(), .true.) .and. checkForEvent())
+        call gmsh%fltk%wait()
+    end do
+end if
+
+call gmsh%finalize()
+
+contains
+subroutine partitionMesh()
+    real(c_double), allocatable :: val(:)
+    integer(c_int) :: N
+    ! Number of partitions
+
+    call gmsh%onelab%getNumber("Parameters/1Number of partitions", val)
+    N = int(val(1), kind=c_int); deallocate(val)
+
+    ! Should we create the boundary representation of the partition entities?
+    call gmsh%onelab%getNumber("Parameters/2Create partition topology (BRep)?", val)
+    call gmsh%option%setNumber("Mesh.PartitionCreateTopology", val(1)); deallocate(val)
+
+    ! Should we create ghost cells?
+    call gmsh%onelab%getNumber("Parameters/3Create ghost cells?", val)
+    call gmsh%option%setNumber("Mesh.PartitionCreateGhostCells", val(1)); deallocate(val)
+
+    ! Should we automatically create new physical groups on the partition
+    ! entities?
+    call gmsh%onelab%getNumber("Parameters/3Create new physical groups?", val)
+    call gmsh%option%setNumber("Mesh.PartitionCreatePhysicals", val(1)); deallocate(val)
+
+    ! Should we keep backward compatibility with pre-Gmsh 4, e.g. to save the
+    ! mesh in MSH2 format?
+    call gmsh%option%setNumber("Mesh.PartitionOldStyleMsh2", 0d0)
+
+    ! Should we save one mesh file per partition?
+    call gmsh%onelab%getNumber("Parameters/4Write one file per partition?", val)
+    call gmsh%option%setNumber("Mesh.PartitionSplitMeshFiles", val(1)); deallocate(val)
+
+    call gmsh%onelab%getNumber("Parameters/0Mesh partitioner", val)
+    if (val(1) == 0) then
+        ! Use Metis to create N partitions
+        call gmsh%model%mesh%partition(N)
+        ! Several options can be set to control Metis: `Mesh.MetisAlgorithm' (1:
+        ! Recursive, 2: K-way), `Mesh.MetisObjective' (1: min. edge-cut, 2:
+        ! min. communication volume), `Mesh.PartitionTriWeight' (weight of
+        ! triangles), `Mesh.PartitionQuadWeight' (weight of quads), ...
+    else
+        ! Use the `SimplePartition' plugin to create chessboard-like partitions
+        call gmsh%plugin%setNumber("SimplePartition", "NumSlicesX", real(N, c_double))
+        call gmsh%plugin%setNumber("SimplePartition", "NumSlicesY", 1d0)
+        call gmsh%plugin%setNumber("SimplePartition", "NumSlicesZ", 1d0)
+        ret = gmsh%plugin%run("SimplePartition")
+    end if
+    deallocate(val)
+
+    ! Save mesh file (or files, if `Mesh.PartitionSplitMeshFiles' is set):
+    call gmsh%onelab%getNumber("Parameters/3Write file to disk?", val)
+    if (val(1) == 1) then
+        call gmsh%write("t21.msh")
+    end if
+    ! Iterate over partitioned entities and print some info (see the first
+    ! extended tutorial `x1.f90' for additional information):
+    ! call gmsh%model%getEntities(entities)
+    ! do e = 1, size(entities)
+    !     partitions = call gmsh%model%getPartitions(e[0], e[1])
+    !     if (size(partitions)) then
+    !         print*, "Entity " + str(e) + " of type " // &
+    !               call gmsh%model%getType(e[0], e[1]))
+    !         print*, " - Partition(s): " + str(partitions)
+    !         print*, " - Parent: " + str(call gmsh%model%getParent(e[0], e[1]))
+    !         print*, " - Boundary: " + str(call gmsh%model%getBoundary([e]))
+    !     end if
+    ! end do
+end subroutine partitionMesh
+
+! Launch the GUI and handle the "check" event (recorded in the "ONELAB/Action"
+! parameter) to recreate the geometry with a new twisting angle if necessary:
+logical function checkForEvent() result(val)
+  character(len=GMSH_API_MAX_STR_LEN), allocatable :: action(:)
+
+  val = .false.
+  call gmsh%onelab%getString("ONELAB/Action", action)
+  if (size(action) > 0 .and. trim(action(1)) == "check") then
+    call gmsh%onelab%setString("ONELAB/Action", [""])
+    call partitionMesh()
+    call gmsh%graphics%draw()
+  end if
+  val = .true.
+end function checkForEvent
+
+end program t21
diff --git a/tutorials/fortran/t3.f90 b/tutorials/fortran/t3.f90
new file mode 100644
index 0000000000000000000000000000000000000000..120e9f61031eaf25f2be96c2c4c2d9772112109c
--- /dev/null
+++ b/tutorials/fortran/t3.f90
@@ -0,0 +1,173 @@
+! ------------------------------------------------------------------------------
+!
+!  Gmsh Fortran tutorial 3
+!
+!  Extruded meshes, ONELAB parameters, options
+!
+! ------------------------------------------------------------------------------
+program t3
+use, intrinsic :: iso_c_binding
+use gmsh
+
+implicit none
+type(gmsh_t) :: gmsh
+integer(c_int) :: i, r, g, b, a
+real(c_double) :: lc
+character(len=GMSH_API_MAX_STR_LEN), allocatable :: argv(:)
+
+allocate(argv(command_argument_count() + 1))
+do i = 0, size(argv) - 1
+    call get_command_argument(i, argv(i+1))
+    argv(i+1) = trim(argv(i+1))
+end do
+call gmsh%initialize(argv)
+
+! Let us now change some options... Since all interactive options are accessible
+! through the API, we can for example make point tags visible or redefine some
+! colors:
+call gmsh%option%setNumber("Geometry.PointNumbers", 1d0)
+call gmsh%option%setColor("Geometry.Color.Points", 255, 165, 0)
+call gmsh%option%setColor("General.Color.Text", 255, 255, 255)
+call gmsh%option%setColor("Mesh.Color.Points", 255, 0, 0)
+
+! Note that for conciseness "Color." can be omitted in color options:
+call gmsh%option%getColor("Geometry.Points", r, g, b, a)
+call gmsh%option%setColor("Geometry.Surfaces", r, g, b, a)
+
+! We create a ONELAB parameter to define the angle of the twist. ONELAB
+! parameters can be modified interactively in the GUI, and can be exchanged with
+! other codes connected to the same ONELAB database. The database can be
+! accessed through the Gmsh Fortran API using JSON-formatted strings (see
+! https://gitlab.onelab.info/doc/tutorials/-/wikis/ONELAB-JSON-interface for
+! more information):
+call gmsh%onelab%set('['//&
+  '{'//&
+    '"type":"number",'//&
+    '"name":"Parameters/Twisting angle",'//&
+    '"values":[90],'//&
+    '"min":0,'//&
+    '"max":120,'//&
+    '"step":1'//&
+  '}'//&
+']')
+
+! Create the geometry and mesh it:
+call createGeometryAndMesh()
+
+if (.not. any(argv == "-nopopup")) then
+call gmsh%fltk%initialize()
+  do while (transfer(gmsh%fltk%isAvailable(), .true.) .and. checkForEvent())
+    call gmsh%fltk%wait()
+  end do
+end if
+
+! When the GUI is launched, you can use the `Help->Current Options and
+! Workspace' menu to see the current values of all options. To save the options
+! in a file, use `File->Export->Gmsh Options', or through the api:
+
+! gmsh%write("t3.opt");
+
+call gmsh%finalize()
+
+contains
+  subroutine createGeometryAndMesh()
+    integer(c_int) :: ret
+    real(c_double) :: h
+    integer(c_int), allocatable :: ov(:,:)
+    real(c_double), allocatable :: angles(:)
+    ! Clear all models and create a new one
+    call gmsh%clear()
+    call gmsh%model%add("t3")
+
+    ! Copied from `t1.f90'...
+    lc = 1e-2
+    ret = gmsh%model%geo%addPoint(.0d0, .0d0, 0d0, lc, 1)
+    ret = gmsh%model%geo%addPoint(.1d0, .0d0, 0d0, lc, 2)
+    ret = gmsh%model%geo%addPoint(.1d0, .3d0, 0d0, lc, 3)
+    ret = gmsh%model%geo%addPoint(.0d0, .3d0, 0d0, lc, 4)
+    ret = gmsh%model%geo%addLine(1, 2, 1)
+    ret = gmsh%model%geo%addLine(3, 2, 2)
+    ret = gmsh%model%geo%addLine(3, 4, 3)
+    ret = gmsh%model%geo%addLine(4, 1, 4)
+    ret = gmsh%model%geo%addCurveLoop([4, 1, -2, 3], 1)
+    ret = gmsh%model%geo%addPlaneSurface([1], 1)
+    call gmsh%model%geo%synchronize()
+    ret = gmsh%model%addPhysicalGroup(1, [1, 2, 4], 5)
+    ret = gmsh%model%addPhysicalGroup(2, [1], name="My surface")
+
+    ! As in `t2.f90', we plan to perform an extrusion along the z axis.  But
+    ! here, instead of only extruding the geometry, we also want to extrude the
+    ! 2D mesh. This is done with the same `extrude()' function, but by
+    ! specifying element 'Layers' (2 layers in this case, the first one with 8
+    ! subdivisions and the second one with 2 subdivisions, both with a height of
+    ! h/2). The number of elements for each layer and the (end) height of each
+    ! layer are specified in two vectors:
+    h = 0.1
+    call gmsh%model%geo%extrude(reshape([2, 1], [2,1]), &
+                                0d0, 0d0, h, &
+                                outDimTags=ov, &
+                                numElements=[8, 2], &
+                                heights=[0.5d0, 1d0])
+
+    ! The extrusion can also be performed with a rotation instead of a
+    ! translation, and the resulting mesh can be recombined into prisms (we use
+    ! only one layer here, with 7 subdivisions). All rotations are specified by
+    ! an an axis point (-0.1, 0, 0.1), an axis direction (0, 1, 0), and a
+    ! rotation angle (-Pi/2):
+    deallocate(ov)
+    call gmsh%model%geo%revolve(reshape([2, 28], [2,1]), &
+                                -0.1d0, 0d0, 0.1d0, &
+                                0d0, 1d0, 0d0, -M_PI / 2d0, &
+                                outDimTags=ov, &
+                                numElements=[7])
+
+    ! Using the built-in geometry kernel, only rotations with angles < Pi are
+    ! supported. To do a full turn, you will thus need to apply at least 3
+    ! rotations. The OpenCASCADE geometry kernel does not have this limitation.
+
+    ! A translation (-2 * h, 0, 0) and a rotation ((0, 0.15, 0.25), (1, 0, 0),
+    ! angle * Pi / 180) can also be combined to form a "twist".  The last
+    ! (optional) argument for the extrude() and twist() functions specifies
+    ! whether the extruded mesh should be recombined or not. The `angle'
+    ! parameter is retrieved from the ONELAB database (it can be set
+    ! interactively in the GUI -- see below):
+    deallocate(ov)
+    call gmsh%onelab%getNumber('Parameters/Twisting angle', angles)
+    call gmsh%model%geo%twist(reshape([2, 50], [2,1]), &
+                              0d0, 0.15d0, 0.25d0, -2 * h, 0d0, 0d0, 1d0, 0d0, 0d0, &
+                              angles(1) * (-M_PI / 180d0), &
+                              outDimTags=ov, &
+                              numElements=[10], &
+                              heights=[real(c_double)::], &
+                              recombine=.true.)
+
+    call gmsh%model%geo%synchronize()
+
+    ! All the extrusion functions return a vector of extruded entities: the
+    ! "top" of the extruded surface (in `ov[0]'), the newly created volume (in
+    ! `ov[1]') and the tags of the lateral surfaces (in `ov[2]', `ov[3]', ...).
+
+    ! We can then define a new physical volume (with tag 101) to group all the
+    ! elementary volumes:
+    ret = gmsh%model%addPhysicalGroup(3, [1, 2, ov(2,2)], 101)
+
+    call gmsh%model%mesh%generate(3)
+    call gmsh%write("t3.msh")
+  end subroutine createGeometryAndMesh
+
+  ! Launch the GUI and handle the "check" event (recorded in the "ONELAB/Action"
+  ! parameter) to recreate the geometry with a new twisting angle if necessary:
+  logical function checkForEvent() result(val)
+    character(len=GMSH_API_MAX_STR_LEN), allocatable :: action(:)
+
+    val = .false.
+    call gmsh%onelab%getString("ONELAB/Action", action)
+    if (size(action) > 0 .and. trim(action(1)) == "check") then
+      call gmsh%onelab%setString("ONELAB/Action", [""])
+      call createGeometryAndMesh()
+      call gmsh%graphics%draw()
+    end if
+    val = .true.
+  end function checkForEvent
+
+end program t3
diff --git a/tutorials/fortran/t4.f90 b/tutorials/fortran/t4.f90
new file mode 100644
index 0000000000000000000000000000000000000000..a321dad65fca27ff21f2935ed0b0d1bc13818b69
--- /dev/null
+++ b/tutorials/fortran/t4.f90
@@ -0,0 +1,185 @@
+! ------------------------------------------------------------------------------
+!
+!  Gmsh Fortran tutorial 4
+!
+!  Holes in surfaces, annotations, entity colors
+!
+! ------------------------------------------------------------------------------
+
+program t4
+use, intrinsic :: iso_c_binding
+use gmsh
+
+implicit none
+type(gmsh_t) :: gmsh
+type(gmsh_model_geo_t) :: factory
+
+integer(c_int) :: i, ret, v
+real(c_double), parameter :: cm = 1e-02
+real(c_double), parameter :: e1 = 4.5 * cm
+real(c_double), parameter :: e2 = 6 * cm / 2
+real(c_double), parameter :: e3 = 5 * cm / 2
+real(c_double), parameter :: h1 = 5 * cm
+real(c_double), parameter :: h2 = 10 * cm
+real(c_double), parameter :: h3 = 5 * cm
+real(c_double), parameter :: h4 = 2 * cm
+real(c_double), parameter :: h5 = 4.5 * cm
+real(c_double), parameter :: R1 = 1 * cm
+real(c_double), parameter :: R2 = 1.5 * cm
+real(c_double), parameter :: r = 1 * cm
+real(c_double), parameter :: Lc1 = 0.01
+real(c_double), parameter :: Lc2 = 0.003
+real(c_double), parameter :: ccos = (-h5 * R1 + e2 * hypot(h5, hypot(e2, R1))) / (h5 * h5 + e2 * e2)
+real(c_double), parameter :: ssin = sqrt(1 - ccos * ccos)
+
+character(len=GMSH_API_MAX_STR_LEN), allocatable :: argv(:)
+
+allocate(argv(command_argument_count() + 1))
+do i = 0, size(argv) - 1
+  call get_command_argument(i, argv(i+1))
+  argv(i+1) = trim(argv(i+1))
+end do
+
+call gmsh%initialize(argv)
+call gmsh%model%add("t4")
+
+ret = factory%addPoint(-e1 - e2, 0d0, 0d0, Lc1, 1)
+ret = factory%addPoint(-e1 - e2, h1, 0d0, Lc1, 2)
+ret = factory%addPoint(-e3 - r, h1, 0d0, Lc2, 3)
+ret = factory%addPoint(-e3 - r, h1 + r, 0d0, Lc2, 4)
+ret = factory%addPoint(-e3, h1 + r, 0d0, Lc2, 5)
+ret = factory%addPoint(-e3, h1 + h2, 0d0, Lc1, 6)
+ret = factory%addPoint(e3, h1 + h2, 0d0, Lc1, 7)
+ret = factory%addPoint(e3, h1 + r, 0d0, Lc2, 8)
+ret = factory%addPoint(e3 + r, h1 + r, 0d0, Lc2, 9)
+ret = factory%addPoint(e3 + r, h1, 0d0, Lc2, 10)
+ret = factory%addPoint(e1 + e2, h1, 0d0, Lc1, 11)
+ret = factory%addPoint(e1 + e2, 0d0, 0d0, Lc1, 12)
+ret = factory%addPoint(e2, 0d0, 0d0, Lc1, 13)
+
+ret = factory%addPoint(R1 / ssin, h5 + R1 * ccos, 0d0, Lc2, 14)
+ret = factory%addPoint(0d0, h5, 0d0, Lc2, 15)
+ret = factory%addPoint(-R1 / ssin, h5 + R1 * ccos, 0d0, Lc2, 16)
+ret = factory%addPoint(-e2, 0d0, 0d0, Lc1, 17)
+
+ret = factory%addPoint(-R2, h1 + h3, 0d0, Lc2, 18)
+ret = factory%addPoint(-R2, h1 + h3 + h4, 0d0, Lc2, 19)
+ret = factory%addPoint(0d0, h1 + h3 + h4, 0d0, Lc2, 20)
+ret = factory%addPoint(R2, h1 + h3 + h4, 0d0, Lc2, 21)
+ret = factory%addPoint(R2, h1 + h3, 0d0, Lc2, 22)
+ret = factory%addPoint(0d0, h1 + h3, 0d0, Lc2, 23)
+
+ret = factory%addPoint(0d0, h1 + h3 + h4 + R2, 0d0, Lc2, 24)
+ret = factory%addPoint(0d0, h1 + h3 - R2, 0d0, Lc2, 25)
+
+ret = factory%addLine(1, 17, 1)
+ret = factory%addLine(17, 16, 2)
+
+! Gmsh provides other curve primitives than straight lines: splines, B-splines,
+! circle arcs, ellipse arcs, etc. Here we define a new circle arc, starting at
+! point 14 and ending at point 16, with the circle's center being the point 15:
+ret = factory%addCircleArc(14, 15, 16, 3)
+
+! Note that, in Gmsh, circle arcs should always be smaller than Pi. The
+! OpenCASCADE geometry kernel does not have this limitation.
+
+! We can then define additional lines and circles, as well as a new surface:
+ret = factory%addLine(14, 13, 4)
+ret = factory%addLine(13, 12, 5)
+ret = factory%addLine(12, 11, 6)
+ret = factory%addLine(11, 10, 7)
+ret = factory%addCircleArc(8, 9, 10, 8)
+ret = factory%addLine(8, 7, 9)
+ret = factory%addLine(7, 6, 10)
+ret = factory%addLine(6, 5, 11)
+ret = factory%addCircleArc(3, 4, 5, 12)
+ret = factory%addLine(3, 2, 13)
+ret = factory%addLine(2, 1, 14)
+ret = factory%addLine(18, 19, 15)
+ret = factory%addCircleArc(21, 20, 24, 16)
+ret = factory%addCircleArc(24, 20, 19, 17)
+ret = factory%addCircleArc(18, 23, 25, 18)
+ret = factory%addCircleArc(25, 23, 22, 19)
+ret = factory%addLine(21, 22, 20)
+
+ret = factory%addCurveLoop([17, -15, 18, 19, -20, 16], 21)
+ret = factory%addPlaneSurface([21], 22)
+
+! But we still need to define the exterior surface. Since this surface has a
+! hole, its definition now requires two curves loops:
+ret = factory%addCurveLoop([11, -12, 13, 14, 1, 2, -3, 4, 5, 6, 7, -8, 9, 10], 23)
+ret = factory%addPlaneSurface([23, 21], 24)
+
+! As a general rule, if a surface has N holes, it is defined by N+1 curve loops:
+! the first loop defines the exterior boundary; the other loops define the
+! boundaries of the holes.
+
+call factory%synchronize()
+
+! Finally, we can add some comments by creating a post-processing view
+! containing some strings:
+v = gmsh%view%add("comments")
+
+! Add a text string in window coordinates, 10 pixels from the left and 10 pixels
+! from the bottom:
+call gmsh%view%addListDataString(v, [10d0, -10d0], ["Created with Gmsh"])
+
+
+! Add a text string in model coordinates centered at (X,Y,Z) = (0, 0.11, 0),
+! with some style attributes:
+call gmsh%view%addListDataString(v, [0d0, 0.11d0, 0d0], ["Hole"], &
+                            ["Align    ", "Center   ", "Font     ", "Helvetica"])
+
+! If a string starts with `file://', the rest is interpreted as an image
+! file. For 3D annotations, the size in model coordinates can be specified after
+! a `@' symbol in the form `widthxheight' (if one of `width' or `height' is
+! zero, natural scaling is used; if both are zero, original image dimensions in
+! pixels are used):
+call gmsh%view%addListDataString(v, [0d0, 0.09d0, 0d0], ["file://../t4_image.png@0.01x0"], &
+                            ["Align ", "Center"])
+
+! The 3D orientation of the image can be specified by proving the direction
+! of the bottom and left edge of the image in model space:
+call gmsh%view%addListDataString(v, [-0.01d0, 0.09d0, 0d0], &
+                            ["file://../t4_image.png@0.01x0,0,0,1,0,1,0"])
+
+! The image can also be drawn in "billboard" mode, i.e. always parallel to
+! the camera, by using the `!' symbol:
+call gmsh%view%addListDataString(v, [0d0, 0.12d0, 0d0], &
+                            ["file://../t4_image.png@0.01x0!"], &
+                            ["Align ", "Center"])
+
+! The size of 2D annotations is given directly in pixels:
+call gmsh%view%addListDataString(v, [150d0, -7d0], ["file://../t4_image.png@20x0"])
+
+! These annotations are handled by a list-based post-processing view. For
+! large post-processing datasets, that contain actual field values defined on
+! a mesh, you should use model-based post-processing views instead, which
+! allow to efficiently store continuous or discontinuous scalar, vector and
+! tensor fields, or arbitrary polynomial order.
+
+! Views and geometrical entities can be made to respond to double-click
+! events, here to print some messages to the console:
+call gmsh%view%option%setString(v, "DoubleClickedCommand", &
+                            "Printf('View[0] has been double-clicked!');")
+call gmsh%option%setString(&
+    "Geometry.DoubleClickedLineCommand", &
+    "Printf('Curve %g has been double-clicked!', "//&
+    "Geometry.DoubleClickedEntityTag);")
+
+! We can also change the color of some entities:
+call gmsh%model%setColor(reshape([2, 22], [2, 1]), 127, 127, 127)  ! Gray50
+call gmsh%model%setColor(reshape([2, 24], [2, 1]), 160, 32, 240)  ! Purple
+call gmsh%model%setColor(reshape([([1, i], i = 1, 15)], [2,14]), 255, 0, 0)  ! Red
+call gmsh%model%setColor(reshape([([1, i], i = 15, 20)], [2,5]), 255, 255, 0)  ! Yellow
+
+call gmsh%model%mesh%generate(2)
+
+call gmsh%write("t4.msh")
+
+! Launch the GUI to see the results:
+if (.not. any(argv == "-nopopup")) call gmsh%fltk%run()
+
+call gmsh%finalize()
+
+end program t4
diff --git a/tutorials/fortran/t5.f90 b/tutorials/fortran/t5.f90
new file mode 100644
index 0000000000000000000000000000000000000000..96755e6dcf8358e576d9dfde8c8421d17b16b6f3
--- /dev/null
+++ b/tutorials/fortran/t5.f90
@@ -0,0 +1,243 @@
+! ------------------------------------------------------------------------------
+!
+!  Gmsh Fortran tutorial 5
+!
+!  Mesh sizes, holes in volumes
+!
+! ------------------------------------------------------------------------------
+program t5
+use, intrinsic :: iso_c_binding
+use gmsh
+
+implicit none
+type(gmsh_t) :: gmsh
+integer(c_int) :: ret, i, t, v
+character(len=GMSH_API_MAX_STR_LEN), allocatable :: argv(:)
+real(c_double), parameter :: lcar1 = .1
+real(c_double), parameter :: lcar2 = .0005
+real(c_double), parameter :: lcar3 = .055
+real(c_double) :: x, y, z, r
+integer(c_int), allocatable :: shells(:)
+
+
+allocate(argv(command_argument_count() + 1))
+do i = 0, size(argv) - 1
+    call get_command_argument(i, argv(i+1))
+    argv(i+1) = trim(argv(i+1))
+end do
+call gmsh%initialize(argv)
+
+call gmsh%model%add("t5")
+
+! If we wanted to change these mesh sizes globally (without changing the above
+! definitions), we could give a global scaling factor for all mesh sizes with
+! e.g.
+!
+! gmsh%option%setNumber("mesh%MeshSizeFactor", 0.1);
+!
+! Since we pass `argc' and `argv' to `gmsh%initialize()', we can also give the
+! option on the command line with the `-clscale' switch. For example, with:
+!
+! > ./t5.exe -clscale 1
+!
+! this tutorial produces a mesh of approximately 3000 nodes and 14,000
+! tetrahedra. With
+!
+! > ./t5.exe -clscale 0.2
+!
+! the mesh counts approximately 231,000 nodes and 1,360,000 tetrahedra. You can
+! check mesh statistics in the graphical user interface (gmsh%fltk.run()) with
+! the `Tools->Statistics' menu.
+!
+! See `t10.f90' for more information about mesh sizes.
+
+! We proceed by defining some elementary entities describing a truncated cube:
+
+ret = gmsh%model%geo%addPoint(0.5d0, 0.5d0, 0.5d0, lcar2, 1)
+ret = gmsh%model%geo%addPoint(0.5d0, 0.5d0, 0.0d0, lcar1, 2)
+ret = gmsh%model%geo%addPoint(0.0d0, 0.5d0, 0.5d0, lcar1, 3)
+ret = gmsh%model%geo%addPoint(0.0d0, 0.0d0, 0.5d0, lcar1, 4)
+ret = gmsh%model%geo%addPoint(0.5d0, 0.0d0, 0.5d0, lcar1, 5)
+ret = gmsh%model%geo%addPoint(0.5d0, 0.0d0, 0.0d0, lcar1, 6)
+ret = gmsh%model%geo%addPoint(0.0d0, 0.5d0, 0.0d0, lcar1, 7)
+ret = gmsh%model%geo%addPoint(0.0d0, 1.0d0, 0.0d0, lcar1, 8)
+ret = gmsh%model%geo%addPoint(1.0d0, 1.0d0, 0.0d0, lcar1, 9)
+ret = gmsh%model%geo%addPoint(0.0d0, 0.0d0, 1.0d0, lcar1, 10)
+ret = gmsh%model%geo%addPoint(0.0d0, 1.0d0, 1.0d0, lcar1, 11)
+ret = gmsh%model%geo%addPoint(1.0d0, 1.0d0, 1.0d0, lcar1, 12)
+ret = gmsh%model%geo%addPoint(1.0d0, 0.0d0, 1.0d0, lcar1, 13)
+ret = gmsh%model%geo%addPoint(1.0d0, 0.0d0, 0.0d0, lcar1, 14)
+
+ret = gmsh%model%geo%addLine(8, 9, 1)
+ret = gmsh%model%geo%addLine(9, 12, 2)
+ret = gmsh%model%geo%addLine(12, 11, 3)
+ret = gmsh%model%geo%addLine(11, 8, 4)
+ret = gmsh%model%geo%addLine(9, 14, 5)
+ret = gmsh%model%geo%addLine(14, 13, 6)
+ret = gmsh%model%geo%addLine(13, 12, 7)
+ret = gmsh%model%geo%addLine(11, 10, 8)
+ret = gmsh%model%geo%addLine(10, 13, 9)
+ret = gmsh%model%geo%addLine(10, 4, 10)
+ret = gmsh%model%geo%addLine(4, 5, 11)
+ret = gmsh%model%geo%addLine(5, 6, 12)
+ret = gmsh%model%geo%addLine(6, 2, 13)
+ret = gmsh%model%geo%addLine(2, 1, 14)
+ret = gmsh%model%geo%addLine(1, 3, 15)
+ret = gmsh%model%geo%addLine(3, 7, 16)
+ret = gmsh%model%geo%addLine(7, 2, 17)
+ret = gmsh%model%geo%addLine(3, 4, 18)
+ret = gmsh%model%geo%addLine(5, 1, 19)
+ret = gmsh%model%geo%addLine(7, 8, 20)
+ret = gmsh%model%geo%addLine(6, 14, 21)
+
+ret = gmsh%model%geo%addCurveLoop([-11, -19, -15, -18], 22)
+ret = gmsh%model%geo%addPlaneSurface([22], 23)
+ret = gmsh%model%geo%addCurveLoop([16, 17, 14, 15], 24)
+ret = gmsh%model%geo%addPlaneSurface([24], 25)
+ret = gmsh%model%geo%addCurveLoop([-17, 20, 1, 5, -21, 13], 26)
+ret = gmsh%model%geo%addPlaneSurface([26], 27)
+ret = gmsh%model%geo%addCurveLoop([-4, -1, -2, -3], 28)
+ret = gmsh%model%geo%addPlaneSurface([28], 29)
+ret = gmsh%model%geo%addCurveLoop([-7, 2, -5, -6], 30)
+ret = gmsh%model%geo%addPlaneSurface([30], 31)
+ret = gmsh%model%geo%addCurveLoop([6, -9, 10, 11, 12, 21], 32)
+ret = gmsh%model%geo%addPlaneSurface([32], 33)
+ret = gmsh%model%geo%addCurveLoop([7, 3, 8, 9], 34)
+ret = gmsh%model%geo%addPlaneSurface([34], 35)
+ret = gmsh%model%geo%addCurveLoop([-10, 18, -16, -20, 4, -8], 36)
+ret = gmsh%model%geo%addPlaneSurface([36], 37)
+ret = gmsh%model%geo%addCurveLoop([-14, -13, -12, 19], 38)
+ret = gmsh%model%geo%addPlaneSurface([38], 39)
+
+
+shells = [gmsh%model%geo%addSurfaceLoop([35, 31, 29, 37, 33, 23, 39, 25, 27])]
+
+! We create five holes in the cube:
+x = 0
+y = 0.75
+z = 0
+r = 0.09
+do t = 1, 5
+  x = x + 0.166
+  z = z + 0.166
+  v = cheeseHole(x, y, z, r, lcar3, shells)
+  ret = gmsh%model%geo%addPhysicalGroup(3, [v], t)
+end do
+
+! The volume of the cube, without the 5 holes, is defined by 6 surface loops:
+! the first surface loop defines the exterior surface; the surface loops other
+! than the first one define holes:
+ret = gmsh%model%geo%addVolume(shells, 186)
+print*, repeat("-", 80)
+call gmsh%model%geo%synchronize()
+
+! Note that using solid modelling with the OpenCASCADE CAD kernel, the same
+! geometry could be built quite differently: see `t16.f90'.
+
+! We finally define a physical volume for the elements discretizing the cube,
+! without the holes (for which physical groups were already defined in the
+! `cheeseHole()' function):
+ret = gmsh%model%addPhysicalGroup(3, [186], 10)
+
+! We could make only part of the model visible to only mesh this subset:
+! ent = gmsh%model%getEntities()
+! gmsh%model%setVisibility(ent, False)
+! gmsh%model%setVisibility([(3, 5(], True, True)
+! gmsh%option%setNumber("mesh%MeshOnlyVisible", 1)
+
+! Meshing algorithms can changed globally using options:
+call gmsh%option%setNumber("Mesh.Algorithm", 6d0)  ! Frontal-Delaunay for 2D meshes
+
+! They can also be set for individual surfaces, e.g. for using `MeshAdapt' on
+! surface 1:
+call gmsh%model%mesh%setAlgorithm(2, 33, 1)
+
+! To generate a curvilinear mesh and optimize it to produce provably valid
+! curved elements (see A. Johnen, J.-F. Remacle and C. Geuzaine. Geometric
+! validity of curvilinear finite elements. Journal of Computational Physics
+! 233, pp. 359-372, 2013; and T. Toulorge, C. Geuzaine, J.-F. Remacle,
+! J. Lambrechts. Robust untangling of curvilinear meshes. Journal of
+! Computational Physics 254, pp. 8-26, 2013), you can uncomment the following
+! lines:
+!
+! gmsh%option%setNumber("mesh%ElementOrder", 2)
+! gmsh%option%setNumber("mesh%HighOrderOptimize", 2)
+
+call gmsh%model%mesh%generate(3)
+call gmsh%write("t5.msh")
+
+! Launch the GUI to see the results:
+if (.not. any(argv == "-nopopup")) call gmsh%fltk%run()
+call gmsh%finalize()
+
+contains
+
+integer(c_int) function cheeseHole(x, y, z, r, lc, shells) result(v)
+  real(c_double), intent(in) :: x, y, z, r, lc
+  integer(c_int), allocatable, intent(inout) :: shells(:)
+
+  integer(c_int) :: sl
+  integer(c_int) :: p1, p2, p3, p4, p5, p6, p7
+  integer(c_int) :: c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12
+  integer(c_int) :: l1, l2, l3, l4, l5, l6, l7, l8
+  integer(c_int) :: s1, s2, s3, s4, s5, s6, s7, s8
+  ! This function will create a spherical hole in a volume. We don't specify
+  ! tags manually, and let the functions return them automatically:
+
+  p1 = gmsh%model%geo%addPoint(x, y, z, lc)
+  p2 = gmsh%model%geo%addPoint(x + r, y, z, lc)
+  p3 = gmsh%model%geo%addPoint(x, y + r, z, lc)
+  p4 = gmsh%model%geo%addPoint(x, y, z + r, lc)
+  p5 = gmsh%model%geo%addPoint(x - r, y, z, lc)
+  p6 = gmsh%model%geo%addPoint(x, y - r, z, lc)
+  p7 = gmsh%model%geo%addPoint(x, y, z - r, lc)
+
+  c1 = gmsh%model%geo%addCircleArc(p2, p1, p7)
+  c2 = gmsh%model%geo%addCircleArc(p7, p1, p5)
+  c3 = gmsh%model%geo%addCircleArc(p5, p1, p4)
+  c4 = gmsh%model%geo%addCircleArc(p4, p1, p2)
+  c5 = gmsh%model%geo%addCircleArc(p2, p1, p3)
+  c6 = gmsh%model%geo%addCircleArc(p3, p1, p5)
+  c7 = gmsh%model%geo%addCircleArc(p5, p1, p6)
+  c8 = gmsh%model%geo%addCircleArc(p6, p1, p2)
+  c9 = gmsh%model%geo%addCircleArc(p7, p1, p3)
+  c10 = gmsh%model%geo%addCircleArc(p3, p1, p4)
+  c11 = gmsh%model%geo%addCircleArc(p4, p1, p6)
+  c12 = gmsh%model%geo%addCircleArc(p6, p1, p7)
+
+  l1 = gmsh%model%geo%addCurveLoop([c5, c10, c4])
+  l2 = gmsh%model%geo%addCurveLoop([c9, -c5, c1])
+  l3 = gmsh%model%geo%addCurveLoop([c12, -c8, -c1])
+  l4 = gmsh%model%geo%addCurveLoop([c8, -c4, c11])
+  l5 = gmsh%model%geo%addCurveLoop([-c10, c6, c3])
+  l6 = gmsh%model%geo%addCurveLoop([-c11, -c3, c7])
+  l7 = gmsh%model%geo%addCurveLoop([-c2, -c7, -c12])
+  l8 = gmsh%model%geo%addCurveLoop([-c6, -c9, c2])
+
+  ! We need non-plane surfaces to define the spherical holes. Here we use the
+  ! `gmsh%model%geo%addSurfaceFilling()' function, which can be used for
+  ! surfaces with 3 or 4 curves on their boundary. With the he built-in
+  ! kernel, if the curves are circle arcs, ruled surfaces are created;
+  ! otherwise transfinite interpolation is used.
+  !
+  ! With the OpenCASCADE kernel, `gmsh%model%occ.addSurfaceFilling()' uses a
+  ! much more general generic surface filling algorithm, creating a BSpline
+  ! surface passing through an arbitrary number of boundary curves. The
+  ! `gmsh%model%geo%addThruSections()' allows to create ruled surfaces (see
+  ! `t19.f90').
+
+  s1 = gmsh%model%geo%addSurfaceFilling([l1])
+  s2 = gmsh%model%geo%addSurfaceFilling([l2])
+  s3 = gmsh%model%geo%addSurfaceFilling([l3])
+  s4 = gmsh%model%geo%addSurfaceFilling([l4])
+  s5 = gmsh%model%geo%addSurfaceFilling([l5])
+  s6 = gmsh%model%geo%addSurfaceFilling([l6])
+  s7 = gmsh%model%geo%addSurfaceFilling([l7])
+  s8 = gmsh%model%geo%addSurfaceFilling([l8])
+
+  sl = gmsh%model%geo%addSurfaceLoop([s1, s2, s3, s4, s5, s6, s7, s8])
+  v = gmsh%model%geo%addVolume([sl])
+  shells = [shells, sl]
+end function cheeseHole
+
+end program t5
diff --git a/tutorials/fortran/t6.f b/tutorials/fortran/t6.f
deleted file mode 100644
index 5a6057015905d561118ce13560d47f0bd8589aab..0000000000000000000000000000000000000000
--- a/tutorials/fortran/t6.f
+++ /dev/null
@@ -1,139 +0,0 @@
-c ---------------------------------------------------------------------------
-c
-c   Gmsh Fortran tutorial 6
-c
-c   Transfinite meshes
-c
-c ---------------------------------------------------------------------------
-
-      include "gmshf.h"
-
-      program main
-      use, intrinsic :: iso_c_binding
-      use gmsh_fortran
-
-      implicit none
-      integer(c_int) :: ierr, argc, itmp, i, status, len
-      integer(c_int) :: p1, p2, l1, l2, l3
-      real(c_double) :: lc
-
-      integer(c_int) :: cl1(4) = (/4, 1, -2, 3/)
-      integer(c_int) :: cl2(6) = (/2, -1, 0, 0, 0, -3/)
-      integer(c_int) :: cl3(4) = (/13, 10, 11, 12/)
-      integer(c_int) :: s1(1) = (/1/)
-      integer(c_int) :: s2(1) = (/-2/)
-      integer(c_int) :: s3(1) = (/14/)
-
-      integer(c_int) :: r4(4) = (/2, 1, 1, 4/)
-      integer(c_int) :: ts(4) = (/1, 2, 3, 4/)
-
-      type(c_ptr), allocatable :: argv(:)
-
-      type string
-        character(len = :, kind = c_char), allocatable :: item
-      end type string
-      type(string), allocatable, target :: tmp(:)
-
-      character(80) :: buf
-
-      lc = 1d - 2
-
-      argc = command_argument_count()
-      allocate(argv(argc + 2))
-      allocate(tmp(argc + 1))
-
-      do i = 0, argc
-        call get_command_argument(i, buf, len)
-        tmp(i + 1) % item = buf(1 : len) // c_null_char
-        argv(i + 1) = c_loc(tmp(i + 1) % item)
-      enddo
-      argv(argc + 2) = c_null_ptr
-
-      call gmshInitialize(argc + 1, argv, 1, 0, ierr)
-
-      call gmshModelAdd("t6" // c_null_char, ierr)
-
-      itmp = gmshModelGeoAddPoint(0d0, 0d0, 0d0, lc, 1, ierr)
-      itmp = gmshModelGeoAddPoint(0.1d0, 0d0, 0d0, lc, 2, ierr)
-      itmp = gmshModelGeoAddPoint(0.1d0, 0.3d0, 0d0, lc, 3, ierr)
-      itmp = gmshModelGeoAddPoint(0d0, 0.3d0, 0d0, lc, 4, ierr)
-
-      itmp = gmshModelGeoAddLine(1, 2, 1, ierr)
-      itmp = gmshModelGeoAddLine(3, 2, 2, ierr)
-      itmp = gmshModelGeoAddLine(3, 4, 3, ierr)
-      itmp = gmshModelGeoAddLine(4, 1, 4, ierr)
-
-      itmp = gmshModelGeoAddCurveLoop(cl1, 4_8, 1, 0, ierr)
-      itmp = gmshModelGeoAddPlaneSurface(s1, 1_8, 1, ierr)
-
-      call gmshModelGeoRemove(r4, 4_8, 0, ierr)
-
-      p1 = gmshModelGeoAddPoint(-0.05d0, 0.05d0, 0d0, lc, -1, ierr)
-      p2 = gmshModelGeoAddPoint(-0.05d0, 0.1d0, 0d0, lc, -1, ierr)
-
-      l1 = gmshModelGeoAddLine(1, p1, -1, ierr)
-      l2 = gmshModelGeoAddLine(p1, p2, -1, ierr)
-      l3 = gmshModelGeoAddLine(p2, 4, -1, ierr)
-
-      cl2(3) = l1
-      cl2(4) = l2
-      cl2(5) = l3
-      itmp = gmshModelGeoAddCurveLoop(cl2, 6_8, 2, 0, ierr)
-      itmp = gmshModelGeoAddPlaneSurface(s2, 1_8, 1, ierr)
-
-      call gmshModelGeoMeshSetTransfiniteCurve(2, 20,
-     &     "Progression" // c_null_char, 1d0, ierr)
-      call gmshModelGeoMeshSetTransfiniteCurve(l1, 6,
-     &     "Progression" // c_null_char, 1d0, ierr)
-      call gmshModelGeoMeshSetTransfiniteCurve(l2, 6,
-     &     "Progression" // c_null_char, 1d0, ierr)
-      call gmshModelGeoMeshSetTransfiniteCurve(l3, 10,
-     &     "Progression" // c_null_char, 1d0, ierr)
-      call gmshModelGeoMeshSetTransfiniteCurve(1, 30,
-     &     "Progression" // c_null_char, -1.2d0, ierr)
-      call gmshModelGeoMeshSetTransfiniteCurve(3, 30,
-     &     "Progression" // c_null_char, 1.2d0, ierr)
-
-      call gmshModelGeoMeshSetTransfiniteSurface(1,
-     &     "Left" // c_null_char, ts, 4_8, ierr)
-      call gmshModelGeoMeshSetRecombine(2, 1, 45d0, ierr)
-
-      itmp = gmshModelGeoAddPoint(0.2d0, 0.2d0, 0d0, 1d0, 7, ierr)
-      itmp = gmshModelGeoAddPoint(0.2d0, 0.1d0, 0d0, 1d0, 8, ierr)
-      itmp = gmshModelGeoAddPoint(0d0, 0.3d0, 0d0, 1d0, 9, ierr)
-      itmp = gmshModelGeoAddPoint(0.25d0, 0.2d0, 0d0, 1d0, 10, ierr)
-      itmp = gmshModelGeoAddPoint(0.3d0, 0.1d0, 0d0, 1d0, 11, ierr)
-
-      itmp = gmshModelGeoAddLine(8, 11, 10, ierr)
-      itmp = gmshModelGeoAddLine(11, 10, 11, ierr)
-      itmp = gmshModelGeoAddLine(10, 7, 12, ierr)
-      itmp = gmshModelGeoAddLine(7, 8, 13, ierr)
-
-      itmp = gmshModelGeoAddCurveLoop(cl3, 4_8, 14, 0, ierr)
-      itmp = gmshModelGeoAddPlaneSurface(s3, 1_8, 15, ierr)
-
-      do i = 10, 13
-         call gmshModelGeoMeshSetTransfiniteCurve(i, 10,
-     &        "Progression" // c_null_char, 1d0, ierr)
-      enddo
-
-      call gmshModelGeoMeshSetTransfiniteSurface(15,
-     &     "Left" // c_null_char, ts, 0_8, ierr)
-
-      call gmshOptionSetNumber("Mesh.Smoothing" // c_null_char,
-     &     100d0, ierr)
-
-      call gmshModelGeoSynchronize(ierr)
-
-      call gmshModelMeshGenerate(2, ierr)
-      call gmshWrite("t6.msh" // c_null_char, ierr)
-
-c     call gmshFltkRun(ierr)
-
-      call gmshFinalize(ierr)
-
-      deallocate(tmp)
-      deallocate(argv)
-
-      stop
-      end
diff --git a/tutorials/fortran/t6.f90 b/tutorials/fortran/t6.f90
new file mode 100644
index 0000000000000000000000000000000000000000..494cb49a808f60e3c6d14132323379a5803d489b
--- /dev/null
+++ b/tutorials/fortran/t6.f90
@@ -0,0 +1,114 @@
+! ------------------------------------------------------------------------------
+!
+!  Gmsh Fortran tutorial 6
+!
+!  Transfinite meshes
+!
+! ------------------------------------------------------------------------------
+
+program t6
+use, intrinsic :: iso_c_binding
+use gmsh
+
+implicit none
+type(gmsh_t) :: gmsh
+integer(c_int) :: ret, i
+integer(c_int) :: p1, p2, l1, l2, l3
+real(c_double), parameter :: lc = 1e-2
+character(len=GMSH_API_MAX_STR_LEN) :: cmd
+
+call gmsh%initialize()
+call gmsh%model%add("t6")
+
+! Copied from `t1.py'...
+ret = gmsh%model%geo%addPoint(0.0d0, 0.0d0, 0.0d0, lc, 1)
+ret = gmsh%model%geo%addPoint(0.1d0, 0.0d0, 0.0d0, lc, 2)
+ret = gmsh%model%geo%addPoint(0.1d0, 0.3d0, 0.0d0, lc, 3)
+ret = gmsh%model%geo%addPoint(0.0d0, 0.3d0, 0.0d0, lc, 4)
+ret = gmsh%model%geo%addLine(1, 2, 1)
+ret = gmsh%model%geo%addLine(3, 2, 2)
+ret = gmsh%model%geo%addLine(3, 4, 3)
+ret = gmsh%model%geo%addLine(4, 1, 4)
+ret = gmsh%model%geo%addCurveLoop([4, 1, -2, 3], 1)
+ret = gmsh%model%geo%addPlaneSurface([1], 1)
+
+! Delete the surface and the left line, and replace the line with 3 new ones:
+call gmsh%model%geo%remove(reshape([2, 1, 1, 4], [2, 2]))
+
+p1 = gmsh%model%geo%addPoint(-0.05d0, 0.05d0, 0.0d0, lc)
+p2 = gmsh%model%geo%addPoint(-0.05d0, 0.10d0, 0.0d0, lc)
+l1 = gmsh%model%geo%addLine(1, p1)
+l2 = gmsh%model%geo%addLine(p1, p2)
+l3 = gmsh%model%geo%addLine(p2, 4)
+
+! Create surface
+ret = gmsh%model%geo%addCurveLoop([2, -1, l1, l2, l3, -3], 2)
+ret = gmsh%model%geo%addPlaneSurface([-2], 1)
+
+! The `setTransfiniteCurve()' meshing constraints explicitly specifies the
+! location of the nodes on the curve. For example, the following command forces
+! 20 uniformly placed nodes on curve 2 (including the nodes on the two end
+! points):
+call gmsh%model%geo%mesh%setTransfiniteCurve(2, 20)
+
+! Let's 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 nodes, but 20!)
+call gmsh%model%geo%mesh%setTransfiniteCurve(l1, 6)
+call gmsh%model%geo%mesh%setTransfiniteCurve(l2, 6)
+call gmsh%model%geo%mesh%setTransfiniteCurve(l3, 10)
+
+! Finally, we put 30 nodes following a geometric progression on curve 1
+! (reversed) and on curve 3: Put 30 points following a geometric progression
+call gmsh%model%geo%mesh%setTransfiniteCurve(1, 30, "Progression", -1.2d0)
+call gmsh%model%geo%mesh%setTransfiniteCurve(3, 30, "Progression", +1.2d0)
+
+! The `setTransfiniteSurface()' meshing constraint uses a transfinite
+! interpolation algorithm in the parametric plane of the surface to connect the
+! nodes on the boundary using a structured grid. If the surface has more than 4
+! corner points, the corners of the transfinite interpolation have to be
+! specified by hand:
+call gmsh%model%geo%mesh%setTransfiniteSurface(1, "Left", [1, 2, 3, 4])
+
+! To create quadrangles instead of triangles, one can use the `setRecombine'
+! constraint:
+call gmsh%model%geo%mesh%setRecombine(2, 1)
+
+! When the surface has only 3 or 4 points on its boundary the list of corners
+! can be omitted in the `setTransfiniteSurface()' call:
+ret = gmsh%model%geo%addPoint(0.20d0, 0.2d0, 0.0d0, 1.0d0, 7)
+ret = gmsh%model%geo%addPoint(0.20d0, 0.1d0, 0.0d0, 1.0d0, 8)
+ret = gmsh%model%geo%addPoint(0.00d0, 0.3d0, 0.0d0, 1.0d0, 9)
+ret = gmsh%model%geo%addPoint(0.25d0, 0.2d0, 0.0d0, 1.0d0, 10)
+ret = gmsh%model%geo%addPoint(0.30d0, 0.1d0, 0.0d0, 1.0d0, 11)
+ret = gmsh%model%geo%addLine(8, 11, 10)
+ret = gmsh%model%geo%addLine(11, 10, 11)
+ret = gmsh%model%geo%addLine(10, 7, 12)
+ret = gmsh%model%geo%addLine(7, 8, 13)
+ret = gmsh%model%geo%addCurveLoop([13, 10, 11, 12], 14)
+ret = gmsh%model%geo%addPlaneSurface([14], 15)
+do i = 10, 13
+    call gmsh%model%geo%mesh%setTransfiniteCurve(i, 10)
+end do
+call gmsh%model%geo%mesh%setTransfiniteSurface(15)
+
+! The way triangles are generated can be controlled by specifying "Left",
+! "Right" or "Alternate" in `setTransfiniteSurface()' command. Try e.g.
+!
+! gmsh%model%geo%mesh%setTransfiniteSurface(15, "Alternate")
+
+call gmsh%model%geo%synchronize()
+
+! Finally we apply an elliptic smoother to the grid to have a more regular
+! mesh:
+call gmsh%option%setNumber("Mesh.Smoothing", 100d0)
+
+call gmsh%model%mesh%generate(2)
+call gmsh%write("t6.msh")
+
+! Launch the GUI to see the results:
+call get_command(cmd)
+if (index(cmd, "-nopopup") == 0) call gmsh%fltk%run()
+call gmsh%finalize()
+
+end program t6
diff --git a/tutorials/fortran/t7.f90 b/tutorials/fortran/t7.f90
new file mode 100644
index 0000000000000000000000000000000000000000..3c7c324f290e17cbd9dddf03bc36bcccde0e354e
--- /dev/null
+++ b/tutorials/fortran/t7.f90
@@ -0,0 +1,72 @@
+! ------------------------------------------------------------------------------
+!
+!  Gmsh Fortran tutorial 7
+!
+!  Background meshes
+!
+! ------------------------------------------------------------------------------
+
+program t7
+
+use, intrinsic :: iso_c_binding
+use gmsh
+
+implicit none
+type(gmsh_t) :: gmsh
+integer(c_int) :: ret
+real(c_double), parameter :: lc = 1e-2
+character(len=GMSH_API_MAX_STR_LEN) :: cmd
+
+! Mesh sizes can be specified very accurately by providing a background mesh,
+! i.e., a post-processing view that contains the target mesh sizes.
+
+call gmsh%initialize()
+
+! Merge a list-based post-processing view containing the target mesh sizes:
+call gmsh%merge('../t7_bgmesh.pos')  ! Only works on UNIX systems.
+
+! If the post-processing view was model-based instead of list-based (i.e. if it
+! was based on an actual mesh), we would need to create a new model to contain
+! the geometry so that meshing it does not destroy the background mesh. It's not
+! necessary here since the view is list-based, but it does no harm:
+call gmsh%model%add("t7")
+
+! Create a simple rectangular geometry:
+ret = gmsh%model%geo%addPoint(.0d0, .0d0, 0d0, lc, 1)
+ret = gmsh%model%geo%addPoint(.1d0, .0d0, 0d0, lc, 2)
+ret = gmsh%model%geo%addPoint(.1d0, .3d0, 0d0, lc, 3)
+ret = gmsh%model%geo%addPoint(.0d0, .3d0, 0d0, lc, 4)
+ret = gmsh%model%geo%addLine(1, 2, 1)
+ret = gmsh%model%geo%addLine(3, 2, 2)
+ret = gmsh%model%geo%addLine(3, 4, 3)
+ret = gmsh%model%geo%addLine(4, 1, 4)
+ret = gmsh%model%geo%addCurveLoop([4, 1, -2, 3], 1)
+ret = gmsh%model%geo%addPlaneSurface([1], 1)
+call gmsh%model%geo%synchronize()
+
+! Add the post-processing view as a new size field:
+ret = gmsh%model%mesh%field%add("PostView")
+call gmsh%model%mesh%field%setNumber(ret, "ViewIndex", 0d0)
+
+! Apply the view as the current background mesh size field:
+call gmsh%model%mesh%field%setAsBackgroundMesh(ret)
+
+! In order to compute the mesh sizes from the background mesh only, and
+! disregard any other size constraints, one can set:
+call gmsh%option%setNumber("Mesh.MeshSizeExtendFromBoundary", 0d0)
+call gmsh%option%setNumber("Mesh.MeshSizeFromPoints", 0d0)
+call gmsh%option%setNumber("Mesh.MeshSizeFromCurvature", 0d0)
+
+! See `t10.f90' for additional information: background meshes are actually a
+! particular case of general "mesh size fields".
+
+call gmsh%model%mesh%generate(2)
+call gmsh%write("t7.msh")
+
+! Launch the GUI to see the results:
+call get_command(cmd)
+if (index(cmd, "-nopopup") == 0) call gmsh%fltk%run()
+
+call gmsh%finalize()
+
+end program t7
diff --git a/tutorials/fortran/t8.f90 b/tutorials/fortran/t8.f90
new file mode 100644
index 0000000000000000000000000000000000000000..7e94e073cfe532d972d79a05b27fc26ac6b5f3ad
--- /dev/null
+++ b/tutorials/fortran/t8.f90
@@ -0,0 +1,188 @@
+! ------------------------------------------------------------------------------
+!
+!  Gmsh Fortran tutorial 8
+!
+!  Post-processing and animations
+!
+! ------------------------------------------------------------------------------
+
+program t8
+
+! In addition to creating geometries and meshes, the Fortran API can also be used
+! to manipulate post-processing datasets (called "views" in Gmsh).
+
+
+use, intrinsic :: iso_c_binding
+use gmsh
+
+implicit none
+type(gmsh_t) :: gmsh
+integer(c_int) :: ret, num, num2, vv, t, frames
+integer(c_int), allocatable :: v(:)
+real(c_double) :: max_step, current_step, tmp, tmp_max
+real(c_double), parameter :: lc = 1e-2
+character(len=GMSH_API_MAX_STR_LEN) :: cmd, num2_str
+integer(c_int), parameter :: white(3) = [255,255,255], black(3) = [0,0,0]
+
+call gmsh%initialize()
+
+! We first create a simple geometry
+ret = gmsh%model%geo%addPoint(.0d0, .0d0, 0d0, lc, 1)
+ret = gmsh%model%geo%addPoint(.1d0, .0d0, 0d0, lc, 2)
+ret = gmsh%model%geo%addPoint(.1d0, .3d0, 0d0, lc, 3)
+ret = gmsh%model%geo%addPoint(.0d0, .3d0, 0d0, lc, 4)
+ret = gmsh%model%geo%addLine(1, 2, 1)
+ret = gmsh%model%geo%addLine(3, 2, 2)
+ret = gmsh%model%geo%addLine(3, 4, 3)
+ret = gmsh%model%geo%addLine(4, 1, 4)
+ret = gmsh%model%geo%addCurveLoop([4, 1, -2, 3], 1)
+ret = gmsh%model%geo%addPlaneSurface([1], 1)
+
+call gmsh%model%geo%synchronize()
+
+! We merge some post-processing views to work on
+call gmsh%merge('../view1.pos')
+call gmsh%merge('../view1.pos')
+call gmsh%merge('../view4.pos')  ! contains 2 views inside
+
+! Gmsh can read post-processing views in various formats. Here the `view1.pos'
+! and `view4.pos' files are in the Gmsh "parsed" format, which is interpreted by
+! the GEO script parser. The parsed format should only be used for relatively
+! small datasets of course: for larger datasets using e.g. MSH files is much
+! more efficient. Post-processing views can also be created directly from the
+! Fortran API.
+
+! We then set some general options:
+call gmsh%option%setNumber("General.Trackball", 0d0)
+call gmsh%option%setNumber("General.RotationX", 0d0)
+call gmsh%option%setNumber("General.RotationY", 0d0)
+call gmsh%option%setNumber("General.RotationZ", 0d0)
+
+! Color options are special
+! Setting a color option of "X.Y" actually sets the option "X.Color.Y"
+! Sets "General.Color.Background", etc.
+call gmsh%option%setColor("General.Background", white(1), white(2), white(3))
+call gmsh%option%setColor("General.Foreground", black(1), black(2), black(3))
+call gmsh%option%setColor("General.Text", black(1), black(2), black(3))
+
+call gmsh%option%setNumber("General.Orthographic", 0d0)
+call gmsh%option%setNumber("General.Axes", 0d0)
+call gmsh%option%setNumber("General.SmallAxes", 0d0)
+
+! Show the GUI:
+call get_command(cmd)
+! Launch the GUI to see the results:
+if (index(cmd, "-nopopup") == 0) call gmsh%fltk%run()
+
+! We also set some options for each post-processing view:
+
+! If we were to follow the geo example blindly, we would read the number of
+! views from the relevant option value, and use the gmsh%option%setNumber() and
+! gmsh%option%setString() functions. A nicer way is to use gmsh%view%getTags()
+! and to use the gmsh%view%option%setNumber() and gmsh%view%option%setString()
+! functions.
+call gmsh%view%getTags(v)
+if (size(v) /= 4) then
+    call gmsh%logger%write("Wrong number of views!", "error")
+    call gmsh%finalize()
+    call abort()
+end if
+
+! We set some options for each post-processing view:
+call gmsh%view%option%setNumber(v(1), "IntervalsType", 2d0)
+call gmsh%view%option%setNumber(v(1), "OffsetZ", 0.05d0)
+call gmsh%view%option%setNumber(v(1), "RaiseZ", 0d0)
+call gmsh%view%option%setNumber(v(1), "Light", 1d0)
+call gmsh%view%option%setNumber(v(1), "ShowScale", 0d0)
+call gmsh%view%option%setNumber(v(1), "SmoothNormals", 1d0)
+
+call gmsh%view%option%setNumber(v(2), "IntervalsType", 1d0)
+! Note that we can't yet set the ColorTable in API
+call gmsh%view%option%setNumber(v(2), "NbIso", 10d0)
+call gmsh%view%option%setNumber(v(2), "ShowScale", 0d0)
+
+call gmsh%view%option%setString(v(3), "Name", "Test...")
+call gmsh%view%option%setNumber(v(3), "Axes", 1d0)
+call gmsh%view%option%setNumber(v(3), "IntervalsType", 2d0)
+call gmsh%view%option%setNumber(v(3), "Type", 2d0)
+call gmsh%view%option%setNumber(v(3), "IntervalsType", 2d0)
+call gmsh%view%option%setNumber(v(3), "AutoPosition", 0d0)
+call gmsh%view%option%setNumber(v(3), "PositionX", 85d0)
+call gmsh%view%option%setNumber(v(3), "PositionY", 50d0)
+call gmsh%view%option%setNumber(v(3), "Width", 200d0)
+call gmsh%view%option%setNumber(v(3), "Height", 130d0)
+
+call gmsh%view%option%setNumber(v(4), "Visible", 0d0)
+
+! You can save an MPEG movie directly by selecting `File->Export' in the
+! GUI. Several predefined animations are setup, for looping on all the time
+! steps in views, or for looping between views.
+
+! But the API can be used to build much more complex animations, by changing
+! options at run-time and re-rendering the graphics. Each frame can then be
+! saved to disk as an image, and multiple frames can be encoded to form a
+! movie. Below is an example of such a custom animation.
+
+t = 0  ! Initial step
+
+do num = 1, 3
+
+  ! Set time step
+  do vv = v(1), v(size(v))
+      call gmsh%view%option%setNumber(vv, "TimeStep", real(t, c_double))
+  end do
+
+  call gmsh%view%option%getNumber(v(1), "TimeStep", current_step)
+  call gmsh%view%option%getNumber(v(1), "NbTimeStep", max_step)
+  max_step = max_step - 1
+  if (current_step < max_step) then
+    t = t + 1
+  else
+    t = 0
+  end if
+
+  call gmsh%view%option%getNumber(v(1), "RaiseZ", tmp)
+  call gmsh%view%option%getNumber(v(1), "Max", tmp_max)
+  call gmsh%view%option%setNumber(v(1), "RaiseZ", tmp +  0.01 / tmp_max * t)
+
+  if (num == 3) then
+    ! Resize the graphics when num == 3, to create 640x480 frames
+    call gmsh%option%getNumber("General.MenuWidth", tmp)
+    call gmsh%option%setNumber("General.GraphicsWidth", tmp + 640)
+    call gmsh%option%setNumber("General.GraphicsHeight", 480d0)
+  end if
+
+  frames = 50
+  do num2 = 1, frames-1
+    ! Incrementally rotate the scene
+    call gmsh%option%getNumber("General.RotationX", tmp)
+    call gmsh%option%setNumber("General.RotationX", tmp + 10)
+    call gmsh%option%getNumber("General.RotationX", tmp)
+    call gmsh%option%setNumber("General.RotationY", tmp / 3)
+    call gmsh%option%getNumber("General.RotationZ", tmp)
+    call gmsh%option%setNumber("General.RotationZ", tmp + 0.1)
+
+    ! Draw the scene
+    call gmsh%graphics%draw()
+
+    if (num == 3) then
+      ! Uncomment the following lines to save each frame to an image file
+      write(num2_str, *) num2
+      ! call gmsh%write("t8-"//trim(num2)//".gif")
+      ! call gmsh%write("t8-"//trim(num2)//".ppm")
+      ! call gmsh%write("t8-"//trim(num2)//".jpg")
+    end if
+  end do
+  if (num == 3) then
+    ! Here we could make a system call to generate a movie. For example,
+    ! with ffmeg:
+    end if
+end do
+
+! Launch the GUI to see the results:
+call get_command(cmd)
+if (index(cmd, "-nopopup") == 0) call gmsh%fltk%run()
+
+call gmsh%finalize()
+
+end program t8
diff --git a/tutorials/fortran/t9.f90 b/tutorials/fortran/t9.f90
new file mode 100644
index 0000000000000000000000000000000000000000..f5d3531230c8fb8115601f2375f7a6d3d0ae0629
--- /dev/null
+++ b/tutorials/fortran/t9.f90
@@ -0,0 +1,86 @@
+! ------------------------------------------------------------------------------
+!
+!  Gmsh Fortran tutorial 9
+!
+!  Plugins
+!
+! ------------------------------------------------------------------------------
+
+program t9
+
+! Plugins can be added to Gmsh in order to extend its capabilities. For example,
+! post-processing plugins can modify views, or create new views based on
+! previously loaded views. Several default plugins are statically linked with
+! Gmsh, e.g. Isosurface, CutPlane, CutSphere, Skin, Transform or Smooth.
+!
+! Plugins can be controlled through the API functions with the `gmsh%plugin'
+! prefix, or from the graphical interface (right click on the view button, then
+! `Plugins').
+use, intrinsic :: iso_c_binding
+use gmsh
+
+implicit none
+type(gmsh_t) :: gmsh
+integer(c_int) :: ret, v1, v2
+integer(c_int), allocatable :: v(:)
+character(len=GMSH_API_MAX_STR_LEN) :: cmd
+
+call gmsh%initialize()
+
+! Let us for example include a three-dimensional scalar view:
+call gmsh%merge('../view3.pos')
+call gmsh%view%getTags(v)
+if (size(v) /= 1) then
+  call gmsh%logger%write("Wrong number of views!", "error")
+  call gmsh%finalize()
+  call abort()
+endif
+
+! We then set some options for the `Isosurface' plugin (which extracts an
+! isosurface from a 3D scalar view), and run it:
+call gmsh%plugin%setNumber("Isosurface", "Value", 0.67d0)
+call gmsh%plugin%setNumber("Isosurface", "View", 0d0)
+v1 = gmsh%plugin%run("Isosurface")
+
+! We also set some options for the `CutPlane' plugin (which computes a section
+! of a 3D view using the plane A*x+B*y+C*z+D=0), and then run it:
+call gmsh%plugin%setNumber("CutPlane", "A", 0d0)
+call gmsh%plugin%setNumber("CutPlane", "B", 0.2d0)
+call gmsh%plugin%setNumber("CutPlane", "C", 1d0)
+call gmsh%plugin%setNumber("CutPlane", "D", 0d0)
+call gmsh%plugin%setNumber("CutPlane", "View", 0d0)
+v2 = gmsh%plugin%run("CutPlane")
+
+! Add a title (By convention, for window coordinates a value greater than 99999
+! represents the center. We could also use `General.GraphicsWidth / 2', but that
+! would only center the string for the current window size.):
+call gmsh%plugin%setString("Annotate", "Text", "A nice title")
+call gmsh%plugin%setNumber("Annotate", "X", 1.e5_c_double)
+call gmsh%plugin%setNumber("Annotate", "Y", 50d0)
+call gmsh%plugin%setString("Annotate", "Font", "Times-BoldItalic")
+call gmsh%plugin%setNumber("Annotate", "FontSize", 28d0)
+call gmsh%plugin%setString("Annotate", "Align", "Center")
+call gmsh%plugin%setNumber("Annotate", "View", 0d0)
+ret = gmsh%plugin%run("Annotate")
+
+call gmsh%plugin%setString("Annotate", "Text", "(and a small subtitle)")
+call gmsh%plugin%setNumber("Annotate", "Y", 70d0)
+call gmsh%plugin%setString("Annotate", "Font", "Times-Roman")
+call gmsh%plugin%setNumber("Annotate", "FontSize", 12d0)
+ret = gmsh%plugin%run("Annotate")
+
+! We finish by setting some options:
+call gmsh%view%option%setNumber(v(1), "Light", 1d0)
+call gmsh%view%option%setNumber(v(1), "IntervalsType", 1d0)
+call gmsh%view%option%setNumber(v(1), "NbIso", 6d0)
+call gmsh%view%option%setNumber(v(1), "SmoothNormals", 1d0)
+call gmsh%view%option%setNumber(v1, "IntervalsType", 2d0)
+call gmsh%view%option%setNumber(v2, "IntervalsType", 2d0)
+
+! Launch the GUI to see the results:
+call get_command(cmd)
+if (index(cmd, "-nopopup") == 0) call gmsh%fltk%run()
+
+call gmsh%finalize()
+
+end program t9