!
! Gmsh - Copyright (C) 1997-2024 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.

! Gmsh is an automatic three-dimensional finite element mesh generator with a
! built-in CAD engine and post-processor. Its design goal is to provide a fast,
! light and user-friendly meshing tool with parametric input and flexible
! visualization capabilities. Gmsh is built around four modules (geometry, mesh,
! solver and post-processing), which can be controlled with the graphical user
! interface, from the command line, using text files written in Gmsh's own
! scripting language (.geo files), or through the C++, C, Python, Julia and
! Fortran application programming interface (API).
!
! This file defines the Gmsh Fortran API (v4.13.1).
!
! 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 = 13
  integer, parameter, public :: GMSH_API_VERSION_PATCH = 1
  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.13.1"

  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 :: getMemory => &
        gmshLoggerGetMemory
    procedure, nopass :: getTotalMemory => &
        gmshLoggerGetTotalMemory
    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 :: defeature => &
        gmshModelOccDefeature
    procedure, nopass :: fillet2D => &
        gmshModelOccFillet2D
    procedure, nopass :: chamfer2D => &
        gmshModelOccChamfer2D
    procedure, nopass :: offsetCurve => &
        gmshModelOccOffsetCurve
    procedure, nopass :: getDistance => &
        gmshModelOccGetDistance
    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 :: removeElements => &
        gmshModelMeshRemoveElements
    procedure, nopass :: reverse => &
        gmshModelMeshReverse
    procedure, nopass :: reverseElements => &
        gmshModelMeshReverseElements
    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 :: computeRenumbering => &
        gmshModelMeshComputeRenumbering
    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 :: getVisibility => &
        gmshModelMeshGetVisibility
    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 :: removeEntityName => &
        gmshModelRemoveEntityName
    procedure, nopass :: getPhysicalGroups => &
        gmshModelGetPhysicalGroups
    procedure, nopass :: getEntitiesForPhysicalGroup => &
        gmshModelGetEntitiesForPhysicalGroup
    procedure, nopass :: getEntitiesForPhysicalName => &
        gmshModelGetEntitiesForPhysicalName
    procedure, nopass :: getPhysicalGroupsForEntity => &
        gmshModelGetPhysicalGroupsForEntity
    procedure, nopass :: addPhysicalGroup => &
        gmshModelAddPhysicalGroup
    procedure, nopass :: removePhysicalGroups => &
        gmshModelRemovePhysicalGroups
    procedure, nopass :: setPhysicalName => &
        gmshModelSetPhysicalName
    procedure, nopass :: getPhysicalName => &
        gmshModelGetPhysicalName
    procedure, nopass :: removePhysicalName => &
        gmshModelRemovePhysicalName
    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 :: 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 :: setAttribute => &
        gmshModelSetAttribute
    procedure, nopass :: getAttribute => &
        gmshModelGetAttribute
    procedure, nopass :: getAttributeNames => &
        gmshModelGetAttributeNames
    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
    procedure, nopass :: restoreDefaults => &
        gmshOptionRestoreDefaults
  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
    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)
  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
    gmshIsInitialized = C_API(ierr_=ierr)
  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
    call C_API(ierr_=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)
    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
    call C_API(fileName=istring_(fileName), &
         ierr_=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)
    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
    call C_API(fileName=istring_(fileName), &
         ierr_=ierr)
  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
    call C_API(fileName=istring_(fileName), &
         ierr_=ierr)
  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
    call C_API(ierr_=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 options" chapter of the Gmsh reference manual
  !! (https://gmsh.info/doc/texinfo/gmsh.html#Gmsh-options).
  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
    call C_API(name=istring_(name), &
         value=real(value, c_double), &
         ierr_=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 options" chapter of the Gmsh reference
  !! manual (https://gmsh.info/doc/texinfo/gmsh.html#Gmsh-options).
  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
    call C_API(name=istring_(name), &
         value=value, &
         ierr_=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 options" chapter of the Gmsh reference manual
  !! (https://gmsh.info/doc/texinfo/gmsh.html#Gmsh-options).
  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
    call C_API(name=istring_(name), &
         value=istring_(value), &
         ierr_=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 options" chapter of the Gmsh reference manual
  !! (https://gmsh.info/doc/texinfo/gmsh.html#Gmsh-options).
  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
      type(c_ptr), intent(out) :: 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
    type(c_ptr) :: api_value_
    call C_API(name=istring_(name), &
         api_value_=api_value_, &
         ierr_=ierr)
    value = ostring_(api_value_)
  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 options" chapter of the Gmsh
  !! reference manual (https://gmsh.info/doc/texinfo/gmsh.html#Gmsh-options).
  !! 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
    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)
  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 options" chapter of the Gmsh
  !! reference manual (https://gmsh.info/doc/texinfo/gmsh.html#Gmsh-options).
  !! 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
    call C_API(name=istring_(name), &
         r=r, &
         g=g, &
         b=b, &
         a=a, &
         ierr_=ierr)
  end subroutine gmshOptionGetColor

  !> Restore all options to default settings.
  subroutine gmshOptionRestoreDefaults(ierr)
    interface
    subroutine C_API(ierr_) &
      bind(C, name="gmshOptionRestoreDefaults")
      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
    call C_API(ierr_=ierr)
  end subroutine gmshOptionRestoreDefaults

  !> 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
    call C_API(name=istring_(name), &
         ierr_=ierr)
  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
    call C_API(ierr_=ierr)
  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
    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)
    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
      type(c_ptr), intent(out) :: 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
    type(c_ptr) :: api_name_
    call C_API(api_name_=api_name_, &
         ierr_=ierr)
    name = ostring_(api_name_)
  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
    call C_API(name=istring_(name), &
         ierr_=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)
    interface
    subroutine C_API(api_fileName_, &
                     ierr_) &
      bind(C, name="gmshModelGetFileName")
      use, intrinsic :: iso_c_binding
      type(c_ptr), intent(out) :: 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
    type(c_ptr) :: api_fileName_
    call C_API(api_fileName_=api_fileName_, &
         ierr_=ierr)
    fileName = ostring_(api_fileName_)
  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
    call C_API(fileName=istring_(fileName), &
         ierr_=ierr)
  end subroutine gmshModelSetFileName

  !> Get all the entities in the current model. A model entity is represented by
  !! two integers: its dimension (dim == 0, 1, 2 or 3) and its tag (its unique,
  !! strictly positive identifier). 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) 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
    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)
    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
    call C_API(dim=int(dim, c_int), &
         tag=int(tag, c_int), &
         name=istring_(name), &
         ierr_=ierr)
  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
      type(c_ptr), intent(out) :: 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
    type(c_ptr) :: api_name_
    call C_API(dim=int(dim, c_int), &
         tag=int(tag, c_int), &
         api_name_=api_name_, &
         ierr_=ierr)
    name = ostring_(api_name_)
  end subroutine gmshModelGetEntityName

  !> 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
    call C_API(name=istring_(name), &
         ierr_=ierr)
  end subroutine gmshModelRemoveEntityName

  !> 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) 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
    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)
    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
    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)
    tags = ovectorint_(api_tags_, &
      api_tags_n_)
  end subroutine gmshModelGetEntitiesForPhysicalGroup

  !> Get the model entities (as a vector (dim, tag) pairs) making up the
  !! physical group with name `name'.
  subroutine gmshModelGetEntitiesForPhysicalName(name, &
                                                 dimTags, &
                                                 ierr)
    interface
    subroutine C_API(name, &
                     api_dimTags_, &
                     api_dimTags_n_, &
                     ierr_) &
      bind(C, name="gmshModelGetEntitiesForPhysicalName")
      use, intrinsic :: iso_c_binding
      character(len=1, kind=c_char), dimension(*), intent(in) :: name
      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
    character(len=*), intent(in) :: name
    integer(c_int), dimension(:,:), allocatable, intent(out) :: dimTags
    integer(c_int), intent(out), optional :: ierr
    type(c_ptr) :: api_dimTags_
    integer(c_size_t) :: api_dimTags_n_
    call C_API(name=istring_(name), &
         api_dimTags_=api_dimTags_, &
         api_dimTags_n_=api_dimTags_n_, &
         ierr_=ierr)
    dimTags = ovectorpair_(api_dimTags_, &
      api_dimTags_n_)
  end subroutine gmshModelGetEntitiesForPhysicalName

  !> 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
    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)
    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
    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)
  end function gmshModelAddPhysicalGroup

  !> Remove the physical groups `dimTags' (given as a vector of (dim, tag)
  !! pairs) 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
    call C_API(api_dimTags_=dimTags, &
         api_dimTags_n_=size_gmsh_pair(dimTags), &
         ierr_=ierr)
  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
    call C_API(dim=int(dim, c_int), &
         tag=int(tag, c_int), &
         name=istring_(name), &
         ierr_=ierr)
  end subroutine gmshModelSetPhysicalName

  !> 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
      type(c_ptr), intent(out) :: 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
    type(c_ptr) :: api_name_
    call C_API(dim=int(dim, c_int), &
         tag=int(tag, c_int), &
         api_name_=api_name_, &
         ierr_=ierr)
    name = ostring_(api_name_)
  end subroutine gmshModelGetPhysicalName

  !> 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
    call C_API(name=istring_(name), &
         ierr_=ierr)
  end subroutine gmshModelRemovePhysicalName

  !> 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
    call C_API(dim=int(dim, c_int), &
         tag=int(tag, c_int), &
         newTag=int(newTag, c_int), &
         ierr_=ierr)
  end subroutine gmshModelSetTag

  !> Get the boundary of the model entities `dimTags', given as a vector of
  !! (dim, tag) pairs. 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
    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)
    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 tags of adjacent
  !! entities of dimension `dim' + 1; the `downward' vector returns the tags of
  !! 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
    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)
    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, &
                                               dimTags, &
                                               dim, &
                                               ierr)
    interface
    subroutine C_API(xmin, &
                     ymin, &
                     zmin, &
                     xmax, &
                     ymax, &
                     zmax, &
                     api_dimTags_, &
                     api_dimTags_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_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
    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) :: dimTags
    integer, intent(in), optional :: dim
    integer(c_int), intent(out), optional :: ierr
    type(c_ptr) :: api_dimTags_
    integer(c_size_t) :: api_dimTags_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_dimTags_=api_dimTags_, &
         api_dimTags_n_=api_dimTags_n_, &
         dim=optval_c_int(-1, dim), &
         ierr_=ierr)
    dimTags = ovectorpair_(api_dimTags_, &
      api_dimTags_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
    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)
  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
    gmshModelGetDimension = C_API(ierr_=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, &
                                      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
    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)
  end function gmshModelAddDiscreteEntity

  !> Remove the entities `dimTags' (given as a vector of (dim, tag) pairs) 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
    call C_API(api_dimTags_=dimTags, &
         api_dimTags_n_=size_gmsh_pair(dimTags), &
         recursive=optval_c_bool(.false., recursive), &
         ierr_=ierr)
  end subroutine gmshModelRemoveEntities

  !> 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
      type(c_ptr), intent(out) :: 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
    type(c_ptr) :: api_entityType_
    call C_API(dim=int(dim, c_int), &
         tag=int(tag, c_int), &
         api_entityType_=api_entityType_, &
         ierr_=ierr)
    entityType = ostring_(api_entityType_)
  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
    call C_API(dim=int(dim, c_int), &
         tag=int(tag, c_int), &
         parentDim=parentDim, &
         parentTag=parentTag, &
         ierr_=ierr)
  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
    gmshModelGetNumberOfPartitions = C_API(ierr_=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, &
                                    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
    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)
    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 u, v parametric coordinates on the surface, concatenated: [p1u,
  !! p1v, p2u, ...]). Return 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
    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)
    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 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
    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)
    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 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
    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)
    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 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
    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)
    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
    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)
    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'. The `parametricCoord' vector should contain u and v
  !! coordinates, concatenated: [p1u, p1v, p2u, ...]. `normals' are returned as
  !! a vector 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
    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)
    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 x, y, z
  !! coordinates, concatenated: [p1x, p1y, p1z, p2x, ...]. `parametricCoord'
  !! returns the parametric coordinates t on the curve (if `dim' = 1) or 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
    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)
    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
    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)
    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
    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)
  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 x, y, z coordinates, concatenated: [p1x, p1y,
  !! p1z, p2x, ...]. `parametricCoord' returns the parametric coordinates t on
  !! the curve (if `dim' == 1) or 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
    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)
    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
    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)
    surfaceParametricCoord = ovectordouble_(api_surfaceParametricCoord_, &
      api_surfaceParametricCoord_n_)
  end subroutine gmshModelReparametrizeOnSurface

  !> Set the visibility of the model entities `dimTags' (given as a vector of
  !! (dim, tag) pairs) 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
    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)
  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
    call C_API(dim=int(dim, c_int), &
         tag=int(tag, c_int), &
         value=value, &
         ierr_=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)
    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
    call C_API(value=int(value, c_int), &
         windowIndex=optval_c_int(0, windowIndex), &
         ierr_=ierr)
  end subroutine gmshModelSetVisibilityPerWindow

  !> Set the color of the model entities `dimTags' (given as a vector of (dim,
  !! tag) pairs) 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
    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)
  end subroutine gmshModelSetColor

  !> Get the color of the model entity of dimension `dim' and tag `tag'. If no
  !! color is specified for the entity, return fully transparent blue, i.e. (0,
  !! 0, 255, 0).
  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
    call C_API(dim=int(dim, c_int), &
         tag=int(tag, c_int), &
         r=r, &
         g=g, &
         b=b, &
         a=a, &
         ierr_=ierr)
  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
    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)
  end subroutine gmshModelSetCoordinates

  !> Set the values of the attribute with name `name'.
  subroutine gmshModelSetAttribute(name, &
                                   values, &
                                   ierr)
    interface
    subroutine C_API(name, &
                     api_values_, &
                     api_values_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_values_
      integer(c_size_t), value, intent(in) :: api_values_n_
      integer(c_int), intent(out), optional :: ierr_
    end subroutine C_API
    end interface
    character(len=*), intent(in) :: name
    character(len=*), dimension(:), intent(in) :: values
    integer(c_int), intent(out), optional :: ierr
    character(len=GMSH_API_MAX_STR_LEN, kind=c_char), allocatable :: api_values_strs(:)
    type(c_ptr), allocatable :: api_values_(:)
    call ivectorstring_(values, &
      api_values_strs, &
      api_values_)
    call C_API(name=istring_(name), &
         api_values_=api_values_, &
         api_values_n_=size_gmsh_str(values), &
         ierr_=ierr)
  end subroutine gmshModelSetAttribute

  !> Get the values of the attribute with name `name'.
  subroutine gmshModelGetAttribute(name, &
                                   values, &
                                   ierr)
    interface
    subroutine C_API(name, &
                     api_values_, &
                     api_values_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_values_
      integer(c_size_t), intent(out) :: api_values_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) :: values
    integer(c_int), intent(out), optional :: ierr
    type(c_ptr) :: api_values_
    integer(c_size_t) :: api_values_n_
    call C_API(name=istring_(name), &
         api_values_=api_values_, &
         api_values_n_=api_values_n_, &
         ierr_=ierr)
    values = ovectorstring_(api_values_, &
      api_values_n_)
  end subroutine gmshModelGetAttribute

  !> 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
    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)
    names = ovectorstring_(api_names_, &
      api_names_n_)
  end subroutine gmshModelGetAttributeNames

  !> 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
    call C_API(name=istring_(name), &
         ierr_=ierr)
  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
    call C_API(dim=optval_c_int(3, dim), &
         ierr_=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, &
                                    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
    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)
  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
    call C_API(ierr_=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' (given as a vector of (dim, tag) pairs) 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
    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)
  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
    call C_API(ierr_=ierr)
  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
    call C_API(ierr_=ierr)
  end subroutine gmshModelMeshRefine

  !> Change 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
    call C_API(order=int(order, c_int), &
         ierr_=ierr)
  end subroutine gmshModelMeshSetOrder

  !> Get the last entities `dimTags' (as a vector of (dim, tag) pairs) 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
    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)
    dimTags = ovectorpair_(api_dimTags_, &
      api_dimTags_n_)
  end subroutine gmshModelMeshGetLastEntityError

  !> Get the last node tags `nodeTags' 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
    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)
    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', given as a vector of (dim, tag) pairs. 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
    call C_API(api_dimTags_=dimTags, &
         api_dimTags_n_=size_gmsh_pair(dimTags), &
         ierr_=ierr)
  end subroutine gmshModelMeshClear

  !> Remove the elements with tags `elementTags' from the entity of dimension
  !! `dim' and tag `tag'. If `elementTags' is empty, remove all the elements
  !! classified on the entity. To get consistent node classification on model
  !! entities, `reclassifyNodes()' should be called afterwards.
  subroutine gmshModelMeshRemoveElements(dim, &
                                         tag, &
                                         elementTags, &
                                         ierr)
    interface
    subroutine C_API(dim, &
                     tag, &
                     api_elementTags_, &
                     api_elementTags_n_, &
                     ierr_) &
      bind(C, name="gmshModelMeshRemoveElements")
      use, intrinsic :: iso_c_binding
      integer(c_int), value, intent(in) :: dim
      integer(c_int), value, intent(in) :: tag
      integer(c_size_t), dimension(*), optional :: api_elementTags_
      integer(c_size_t), value, intent(in) :: api_elementTags_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), optional :: elementTags
    integer(c_int), intent(out), optional :: ierr
    call C_API(dim=int(dim, c_int), &
         tag=int(tag, c_int), &
         api_elementTags_=elementTags, &
         api_elementTags_n_=size_gmsh_size(elementTags), &
         ierr_=ierr)
  end subroutine gmshModelMeshRemoveElements

  !> Reverse the orientation of the elements in the entities `dimTags', given as
  !! a vector of (dim, tag) pairs. 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
    call C_API(api_dimTags_=dimTags, &
         api_dimTags_n_=size_gmsh_pair(dimTags), &
         ierr_=ierr)
  end subroutine gmshModelMeshReverse

  !> Reverse the orientation of the elements with tags `elementTags'.
  subroutine gmshModelMeshReverseElements(elementTags, &
                                          ierr)
    interface
    subroutine C_API(api_elementTags_, &
                     api_elementTags_n_, &
                     ierr_) &
      bind(C, name="gmshModelMeshReverseElements")
      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), intent(out), optional :: ierr_
    end subroutine C_API
    end interface
    integer(c_size_t), dimension(:), intent(in) :: elementTags
    integer(c_int), intent(out), optional :: ierr
    call C_API(api_elementTags_=elementTags, &
         api_elementTags_n_=size_gmsh_size(elementTags), &
         ierr_=ierr)
  end subroutine gmshModelMeshReverseElements

  !> 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', given as a
  !! vector of (dim, tag) pairs. 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
    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)
  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
    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)
    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
    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)
    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
    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)
    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
    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)
  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
    call C_API(onlyIfNecessary=optval_c_bool(.true., onlyIfNecessary), &
         ierr_=ierr)
  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
    call C_API(onlyIfNecessary=optval_c_bool(.true., onlyIfNecessary), &
         ierr_=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, &
                                                   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
    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)
    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
    call C_API(maxTag=maxTag, &
         ierr_=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, &
                                   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
    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)
  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
    call C_API(ierr_=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)
    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
    call C_API(dim=optval_c_int(-1, dim), &
         tag=optval_c_int(-1, tag), &
         ierr_=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, &
                                      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
    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)
    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
    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)
    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
    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)
    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
    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)
    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
    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)
  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
    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)
    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
    gmshModelMeshGetElementType = C_API(familyName=istring_(familyName), &
                                  order=int(order, c_int), &
                                  serendip=optval_c_bool(.false., serendip), &
                                  ierr_=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, &
                                               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
      type(c_ptr), intent(out) :: 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
    type(c_ptr) :: api_elementName_
    type(c_ptr) :: api_localNodeCoord_
    integer(c_size_t) :: api_localNodeCoord_n_
    call C_API(elementType=int(elementType, c_int), &
         api_elementName_=api_elementName_, &
         dim=dim, &
         order=order, &
         numNodes=numNodes, &
         api_localNodeCoord_=api_localNodeCoord_, &
         api_localNodeCoord_n_=api_localNodeCoord_n_, &
         numPrimaryNodes=numPrimaryNodes, &
         ierr_=ierr)
    elementName = ostring_(api_elementName_)
    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' (for C++ only; output vectors must be preallocated).
  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
    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)
    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
    call C_API(maxTag=maxTag, &
         ierr_=ierr)
  end subroutine gmshModelMeshGetMaxElementTag

  !> Preallocate data before calling `getElementsByType' with `numTasks' > 1.
  !! For 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
    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)
    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: "minDetJac" and "maxDetJac"
  !! for the adaptively computed minimal and maximal Jacobian determinant,
  !! "minSJ" for the sampled minimal scaled jacobien, "minSICN" for the sampled
  !! minimal signed inverted condition number, "minSIGE" for the sampled signed
  !! inverted gradient error, "gamma" for the ratio of the inscribed to
  !! circumcribed sphere radius, "innerRadius" for the inner radius,
  !! "outerRadius" for the outerRadius, "minIsotropy" for the minimum isotropy
  !! measure, "angleShape" for the angle shape measure, "minEdge" for the
  !! minimum straight edge length, "maxEdge" for the maximum straight edge
  !! length, "volume" for the volume. If `numTasks' > 1, only compute and return
  !! the part of the data indexed by `task' (for C++ only; output vector must be
  !! preallocated).
  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
    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)
    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
    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)
  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
    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)
  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
    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)
    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 u, v, w 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' (for C++ only; output vectors must be
  !! preallocated).
  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
    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)
    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++
  !! 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
    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)
    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 u, v, w 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
    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)
    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 u, v, w 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 the `wantedOrientations' vector 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
    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)
    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. If `numTasks' > 1, only compute and
  !! return the part of the data indexed by `task' (for C++ only; output vector
  !! must be preallocated).
  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
    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)
    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
    call C_API(elementTag=int(elementTag, c_size_t), &
         functionSpaceType=istring_(functionSpaceType), &
         basisFunctionsOrientation=basisFunctionsOrientation, &
         ierr_=ierr)
  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
    gmshModelMeshGetNumberOfOrientations = C_API(elementType=int(elementType, c_int), &
                                           functionSpaceType=istring_(functionSpaceType), &
                                           ierr_=ierr)
  end function gmshModelMeshGetNumberOfOrientations

  !> Preallocate data before calling `getBasisFunctionsOrientation' with
  !! `numTasks' > 1. For 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
    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)
    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
    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)
    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 a multiple of three (if `faceType'
  !! == 3) or four (if `faceType' == 4) node tags 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
    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)
    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', given as a vector of
  !! (dim, tag) pairs.
  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
    call C_API(api_dimTags_=dimTags, &
         api_dimTags_n_=size_gmsh_pair(dimTags), &
         ierr_=ierr)
  end subroutine gmshModelMeshCreateEdges

  !> Create unique mesh faces for the entities `dimTags', given as a vector of
  !! (dim, tag) pairs.
  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
    call C_API(api_dimTags_=dimTags, &
         api_dimTags_n_=size_gmsh_pair(dimTags), &
         ierr_=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, &
                                      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
    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)
    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
    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)
    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
    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)
  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
    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)
  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
    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)
    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
    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)
    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
    gmshModelMeshGetNumberOfKeys = C_API(elementType=int(elementType, c_int), &
                                   functionSpaceType=istring_(functionSpaceType), &
                                   ierr_=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, &
                                             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
    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)
    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' (for C++ only; output vector must be
  !! preallocated).
  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
    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)
    barycenters = ovectordouble_(api_barycenters_, &
      api_barycenters_n_)
  end subroutine gmshModelMeshGetBarycenters

  !> Preallocate data before calling `getBarycenters' with `numTasks' > 1. For
  !! 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
    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)
    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' (for C++ only; output vector must be preallocated).
  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
    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)
    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' (for C++ only; output vector must be preallocated).
  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
    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)
    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
    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)
    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', given as a
  !! vector of (dim, tag) pairs. 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
    call C_API(api_dimTags_=dimTags, &
         api_dimTags_n_=size_gmsh_pair(dimTags), &
         size=real(size, c_double), &
         ierr_=ierr)
  end subroutine gmshModelMeshSetSize

  !> Get the mesh size constraints (if any) associated with the model entities
  !! `dimTags', given as a vector of (dim, tag) pairs. 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
    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)
    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
    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)
  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
    call C_API(callback=callback, &
         ierr_=ierr)
  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
    call C_API(ierr_=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)
    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
    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)
  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
    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)
  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
    call C_API(tag=int(tag, c_int), &
         api_cornerTags_=cornerTags, &
         api_cornerTags_n_=size_gmsh_int(cornerTags), &
         ierr_=ierr)
  end subroutine gmshModelMeshSetTransfiniteVolume

  !> Set transfinite meshing constraints on the model entities in `dimTags',
  !! given as a vector of (dim, tag) pairs. 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
    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)
  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
    call C_API(dim=int(dim, c_int), &
         tag=int(tag, c_int), &
         angle=optval_c_double(45., angle), &
         ierr_=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)
    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
    call C_API(dim=int(dim, c_int), &
         tag=int(tag, c_int), &
         val=int(val, c_int), &
         ierr_=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)
    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
    call C_API(dim=int(dim, c_int), &
         tag=int(tag, c_int), &
         val=optval_c_bool(.true., val), &
         ierr_=ierr)
  end subroutine gmshModelMeshSetReverse

  !> Set the meshing algorithm on the model entity of dimension `dim' and tag
  !! `tag'. Supported values are those of the `Mesh.Algorithm' option, as listed
  !! in the Gmsh reference manual. 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
    call C_API(dim=int(dim, c_int), &
         tag=int(tag, c_int), &
         val=int(val, c_int), &
         ierr_=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)
    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
    call C_API(dim=int(dim, c_int), &
         tag=int(tag, c_int), &
         val=int(val, c_int), &
         ierr_=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, &
                                      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
    call C_API(dim=int(dim, c_int), &
         api_tags_=tags, &
         api_tags_n_=size_gmsh_int(tags), &
         ierr_=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)
    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
    call C_API(tag=int(tag, c_int), &
         ierr_=ierr)
  end subroutine gmshModelMeshSetOutwardOrientation

  !> Remove all meshing constraints from the model entities `dimTags', given as
  !! a vector of (dim, tag) pairs. 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
    call C_API(api_dimTags_=dimTags, &
         api_dimTags_n_=size_gmsh_pair(dimTags), &
         ierr_=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, &
                                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
    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)
  end subroutine gmshModelMeshEmbed

  !> Remove embedded entities from the model entities `dimTags', given as a
  !! vector of (dim, tag) pairs. 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
    call C_API(api_dimTags_=dimTags, &
         api_dimTags_n_=size_gmsh_pair(dimTags), &
         dim=optval_c_int(-1, dim), &
         ierr_=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, &
                                      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
    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)
    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 the `ordering' vector.
  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
    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)
  end subroutine gmshModelMeshReorderElements

  !> Compute a renumbering vector `newTags' corresponding to the input tags
  !! `oldTags' for a given list of element tags `elementTags'. If `elementTags'
  !! is empty, compute the renumbering on the full mesh. If `method' is equal to
  !! "RCMK", compute a node renumering with Reverse Cuthill McKee. If `method'
  !! is equal to "Hilbert", compute a node renumering along a Hilbert curve. If
  !! `method' is equal to "Metis", compute a node renumering using Metis.
  !! Element renumbering is not available yet.
  subroutine gmshModelMeshComputeRenumbering(oldTags, &
                                             newTags, &
                                             method, &
                                             elementTags, &
                                             ierr)
    interface
    subroutine C_API(api_oldTags_, &
                     api_oldTags_n_, &
                     api_newTags_, &
                     api_newTags_n_, &
                     method, &
                     api_elementTags_, &
                     api_elementTags_n_, &
                     ierr_) &
      bind(C, name="gmshModelMeshComputeRenumbering")
      use, intrinsic :: iso_c_binding
      type(c_ptr), intent(out) :: api_oldTags_
      integer(c_size_t), intent(out) :: api_oldTags_n_
      type(c_ptr), intent(out) :: api_newTags_
      integer(c_size_t), intent(out) :: api_newTags_n_
      character(len=1, kind=c_char), dimension(*), intent(in), optional :: method
      integer(c_size_t), dimension(*), optional :: api_elementTags_
      integer(c_size_t), value, intent(in) :: api_elementTags_n_
      integer(c_int), intent(out), optional :: ierr_
    end subroutine C_API
    end interface
    integer(c_size_t), dimension(:), allocatable, intent(out) :: oldTags
    integer(c_size_t), dimension(:), allocatable, intent(out) :: newTags
    character(len=*), intent(in), optional :: method
    integer(c_size_t), dimension(:), intent(in), optional :: elementTags
    integer(c_int), intent(out), optional :: ierr
    type(c_ptr) :: api_oldTags_
    integer(c_size_t) :: api_oldTags_n_
    type(c_ptr) :: api_newTags_
    integer(c_size_t) :: api_newTags_n_
    call C_API(api_oldTags_=api_oldTags_, &
         api_oldTags_n_=api_oldTags_n_, &
         api_newTags_=api_newTags_, &
         api_newTags_n_=api_newTags_n_, &
         method=istring_(optval_c_str("RCMK", method)), &
         api_elementTags_=elementTags, &
         api_elementTags_n_=size_gmsh_size(elementTags), &
         ierr_=ierr)
    oldTags = ovectorsize_(api_oldTags_, &
      api_oldTags_n_)
    newTags = ovectorsize_(api_newTags_, &
      api_newTags_n_)
  end subroutine gmshModelMeshComputeRenumbering

  !> Renumber the node tags. If no explicit renumbering is provided through the
  !! `oldTags' and `newTags' vectors, renumber the nodes in a continuous
  !! sequence, taking into account the subset of elements to be saved later on
  !! if the option "Mesh.SaveAll" is not set.
  subroutine gmshModelMeshRenumberNodes(oldTags, &
                                        newTags, &
                                        ierr)
    interface
    subroutine C_API(api_oldTags_, &
                     api_oldTags_n_, &
                     api_newTags_, &
                     api_newTags_n_, &
                     ierr_) &
      bind(C, name="gmshModelMeshRenumberNodes")
      use, intrinsic :: iso_c_binding
      integer(c_size_t), dimension(*), optional :: api_oldTags_
      integer(c_size_t), value, intent(in) :: api_oldTags_n_
      integer(c_size_t), dimension(*), optional :: api_newTags_
      integer(c_size_t), value, intent(in) :: api_newTags_n_
      integer(c_int), intent(out), optional :: ierr_
    end subroutine C_API
    end interface
    integer(c_size_t), dimension(:), intent(in), optional :: oldTags
    integer(c_size_t), dimension(:), intent(in), optional :: newTags
    integer(c_int), intent(out), optional :: ierr
    call C_API(api_oldTags_=oldTags, &
         api_oldTags_n_=size_gmsh_size(oldTags), &
         api_newTags_=newTags, &
         api_newTags_n_=size_gmsh_size(newTags), &
         ierr_=ierr)
  end subroutine gmshModelMeshRenumberNodes

  !> Renumber the element tags in a continuous sequence. If no explicit
  !! renumbering is provided through the `oldTags' and `newTags' vectors,
  !! renumber the elements in a continuous sequence, taking into account the
  !! subset of elements to be saved later on if the option "Mesh.SaveAll" is not
  !! set.
  subroutine gmshModelMeshRenumberElements(oldTags, &
                                           newTags, &
                                           ierr)
    interface
    subroutine C_API(api_oldTags_, &
                     api_oldTags_n_, &
                     api_newTags_, &
                     api_newTags_n_, &
                     ierr_) &
      bind(C, name="gmshModelMeshRenumberElements")
      use, intrinsic :: iso_c_binding
      integer(c_size_t), dimension(*), optional :: api_oldTags_
      integer(c_size_t), value, intent(in) :: api_oldTags_n_
      integer(c_size_t), dimension(*), optional :: api_newTags_
      integer(c_size_t), value, intent(in) :: api_newTags_n_
      integer(c_int), intent(out), optional :: ierr_
    end subroutine C_API
    end interface
    integer(c_size_t), dimension(:), intent(in), optional :: oldTags
    integer(c_size_t), dimension(:), intent(in), optional :: newTags
    integer(c_int), intent(out), optional :: ierr
    call C_API(api_oldTags_=oldTags, &
         api_oldTags_n_=size_gmsh_size(oldTags), &
         api_newTags_=newTags, &
         api_newTags_n_=size_gmsh_size(newTags), &
         ierr_=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, &
                                      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
    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)
  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
    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)
    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
    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)
    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
    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)
    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
    call C_API(ierr_=ierr)
  end subroutine gmshModelMeshImportStl

  !> Get the `tags' of any duplicate nodes in the mesh of the entities
  !! `dimTags', given as a vector of (dim, tag) pairs. 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
    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)
    tags = ovectorsize_(api_tags_, &
      api_tags_n_)
  end subroutine gmshModelMeshGetDuplicateNodes

  !> Remove duplicate nodes in the mesh of the entities `dimTags', given as a
  !! vector of (dim, tag) pairs. 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
    call C_API(api_dimTags_=dimTags, &
         api_dimTags_n_=size_gmsh_pair(dimTags), &
         ierr_=ierr)
  end subroutine gmshModelMeshRemoveDuplicateNodes

  !> Remove duplicate elements (defined by the same nodes, in the same entity)
  !! in the mesh of the entities `dimTags', given as a vector of (dim, tag)
  !! pairs. 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
    call C_API(api_dimTags_=dimTags, &
         api_dimTags_n_=size_gmsh_pair(dimTags), &
         ierr_=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)
    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
    call C_API(quality=optval_c_double(1., quality), &
         tag=optval_c_int(-1, tag), &
         ierr_=ierr)
  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
    call C_API(api_elementTags_=elementTags, &
         api_elementTags_n_=size_gmsh_size(elementTags), &
         value=int(value, c_int), &
         ierr_=ierr)
  end subroutine gmshModelMeshSetVisibility

  !> Get the visibility of the elements of tags `elementTags'.
  subroutine gmshModelMeshGetVisibility(elementTags, &
                                        values, &
                                        ierr)
    interface
    subroutine C_API(api_elementTags_, &
                     api_elementTags_n_, &
                     api_values_, &
                     api_values_n_, &
                     ierr_) &
      bind(C, name="gmshModelMeshGetVisibility")
      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_values_
      integer(c_size_t), intent(out) :: api_values_n_
      integer(c_int), intent(out), optional :: ierr_
    end subroutine C_API
    end interface
    integer(c_size_t), dimension(:), intent(in) :: elementTags
    integer(c_int), dimension(:), allocatable, intent(out) :: values
    integer(c_int), intent(out), optional :: ierr
    type(c_ptr) :: api_values_
    integer(c_size_t) :: api_values_n_
    call C_API(api_elementTags_=elementTags, &
         api_elementTags_n_=size_gmsh_size(elementTags), &
         api_values_=api_values_, &
         api_values_n_=api_values_n_, &
         ierr_=ierr)
    values = ovectorint_(api_values_, &
      api_values_n_)
  end subroutine gmshModelMeshGetVisibility

  !> 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
    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)
  end subroutine gmshModelMeshClassifySurfaces

  !> Create a geometry for the discrete entities `dimTags' (given as a vector of
  !! (dim, tag) pairs) 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
    call C_API(api_dimTags_=dimTags, &
         api_dimTags_n_=size_gmsh_pair(dimTags), &
         ierr_=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)
    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
    call C_API(makeSimplyConnected=optval_c_bool(.true., makeSimplyConnected), &
         exportDiscrete=optval_c_bool(.true., exportDiscrete), &
         ierr_=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, &
                                             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
    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)
  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
    call C_API(ierr_=ierr)
  end subroutine gmshModelMeshClearHomologyRequests

  !> Perform the (co)homology computations requested by addHomologyRequest().
  !! The newly created physical groups are returned in `dimTags' as a vector of
  !! (dim, tag) pairs.
  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
    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)
    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
    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)
    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
    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)
    tri = ovectorsize_(api_tri_, &
      api_tri_n_)
  end subroutine gmshModelMeshTriangulate

  !> Tetrahedralize the points given in the `coord' vector as x, y, z
  !! coordinates, concatenated, 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
    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)
    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. Available field types are listed in the "Gmsh mesh size
  !! fields" chapter of the Gmsh reference manual
  !! (https://gmsh.info/doc/texinfo/gmsh.html#Gmsh-mesh-size-fields).
  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
    gmshModelMeshFieldAdd = C_API(fieldType=istring_(fieldType), &
                            tag=optval_c_int(-1, tag), &
                            ierr_=ierr)
  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
    call C_API(tag=int(tag, c_int), &
         ierr_=ierr)
  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
    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)
    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
      type(c_ptr), intent(out) :: 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
    type(c_ptr) :: api_fileType_
    call C_API(tag=int(tag, c_int), &
         api_fileType_=api_fileType_, &
         ierr_=ierr)
    fileType = ostring_(api_fileType_)
  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
    call C_API(tag=int(tag, c_int), &
         option=istring_(option), &
         value=real(value, c_double), &
         ierr_=ierr)
  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
    call C_API(tag=int(tag, c_int), &
         option=istring_(option), &
         value=value, &
         ierr_=ierr)
  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
    call C_API(tag=int(tag, c_int), &
         option=istring_(option), &
         value=istring_(value), &
         ierr_=ierr)
  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
      type(c_ptr), intent(out) :: 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
    type(c_ptr) :: api_value_
    call C_API(tag=int(tag, c_int), &
         option=istring_(option), &
         api_value_=api_value_, &
         ierr_=ierr)
    value = ostring_(api_value_)
  end subroutine gmshModelMeshFieldGetString

  !> Set the numerical list option `option' to value `values' for field `tag'.
  subroutine gmshModelMeshFieldSetNumbers(tag, &
                                          option, &
                                          values, &
                                          ierr)
    interface
    subroutine C_API(tag, &
                     option, &
                     api_values_, &
                     api_values_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_values_
      integer(c_size_t), value, intent(in) :: api_values_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) :: values
    integer(c_int), intent(out), optional :: ierr
    call C_API(tag=int(tag, c_int), &
         option=istring_(option), &
         api_values_=values, &
         api_values_n_=size_gmsh_double(values), &
         ierr_=ierr)
  end subroutine gmshModelMeshFieldSetNumbers

  !> Get the value of the numerical list option `option' for field `tag'.
  subroutine gmshModelMeshFieldGetNumbers(tag, &
                                          option, &
                                          values, &
                                          ierr)
    interface
    subroutine C_API(tag, &
                     option, &
                     api_values_, &
                     api_values_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_values_
      integer(c_size_t) :: api_values_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) :: values
    integer(c_int), intent(out), optional :: ierr
    type(c_ptr) :: api_values_
    integer(c_size_t) :: api_values_n_
    call C_API(tag=int(tag, c_int), &
         option=istring_(option), &
         api_values_=api_values_, &
         api_values_n_=api_values_n_, &
         ierr_=ierr)
    values = ovectordouble_(api_values_, &
      api_values_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
    call C_API(tag=int(tag, c_int), &
         ierr_=ierr)
  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
    call C_API(tag=int(tag, c_int), &
         ierr_=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)
    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
    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)
  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
    gmshModelGeoAddLine = C_API(startTag=int(startTag, c_int), &
                          endTag=int(endTag, c_int), &
                          tag=optval_c_int(-1, tag), &
                          ierr_=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)
    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
    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)
  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
    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)
  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
    gmshModelGeoAddSpline = C_API(api_pointTags_=pointTags, &
                            api_pointTags_n_=size_gmsh_int(pointTags), &
                            tag=optval_c_int(-1, tag), &
                            ierr_=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, &
                                  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
    gmshModelGeoAddBSpline = C_API(api_pointTags_=pointTags, &
                             api_pointTags_n_=size_gmsh_int(pointTags), &
                             tag=optval_c_int(-1, tag), &
                             ierr_=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, &
                                 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
    gmshModelGeoAddBezier = C_API(api_pointTags_=pointTags, &
                            api_pointTags_n_=size_gmsh_int(pointTags), &
                            tag=optval_c_int(-1, tag), &
                            ierr_=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, &
                                   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
    gmshModelGeoAddPolyline = C_API(api_pointTags_=pointTags, &
                              api_pointTags_n_=size_gmsh_int(pointTags), &
                              tag=optval_c_int(-1, tag), &
                              ierr_=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, &
                                         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
    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)
  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
    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)
  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
    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)
  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
    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)
    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
    gmshModelGeoAddPlaneSurface = C_API(api_wireTags_=wireTags, &
                                  api_wireTags_n_=size_gmsh_int(wireTags), &
                                  tag=optval_c_int(-1, tag), &
                                  ierr_=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, &
                                         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
    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)
  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
    gmshModelGeoAddSurfaceLoop = C_API(api_surfaceTags_=surfaceTags, &
                                 api_surfaceTags_n_=size_gmsh_int(surfaceTags), &
                                 tag=optval_c_int(-1, tag), &
                                 ierr_=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, &
                                 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
    gmshModelGeoAddVolume = C_API(api_shellTags_=shellTags, &
                            api_shellTags_n_=size_gmsh_int(shellTags), &
                            tag=optval_c_int(-1, tag), &
                            ierr_=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, &
                                   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
    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)
  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
    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)
  end function gmshModelGeoAddPointOnGeometry

  !> Extrude the entities `dimTags' (given as a vector of (dim, tag) pairs) in
  !! the built-in CAD representation, using a translation along (`dx', `dy',
  !! `dz'). Return extruded entities in `outDimTags'. If the `numElements'
  !! vector is not empty, also extrude the mesh: the entries in `numElements'
  !! give the number of elements in each layer. If the `height' vector 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
    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)
    outDimTags = ovectorpair_(api_outDimTags_, &
      api_outDimTags_n_)
  end subroutine gmshModelGeoExtrude

  !> Extrude the entities `dimTags' (given as a vector of (dim, tag) pairs) 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 the `numElements' vector is
  !! not empty, also extrude the mesh: the entries in `numElements' give the
  !! number of elements in each layer. If the `height' vector 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
    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)
    outDimTags = ovectorpair_(api_outDimTags_, &
      api_outDimTags_n_)
  end subroutine gmshModelGeoRevolve

  !> Extrude the entities `dimTags' (given as a vector of (dim, tag) pairs) 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 the `numElements' vector is not empty, also
  !! extrude the mesh: the entries in `numElements' give the number of elements
  !! in each layer. If the `height' vector 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
    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)
    outDimTags = ovectorpair_(api_outDimTags_, &
      api_outDimTags_n_)
  end subroutine gmshModelGeoTwist

  !> Extrude the entities `dimTags' (given as a vector of (dim, tag) pairs) 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
  !! the `height' vector 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
    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)
    outDimTags = ovectorpair_(api_outDimTags_, &
      api_outDimTags_n_)
  end subroutine gmshModelGeoExtrudeBoundaryLayer

  !> Translate the entities `dimTags' (given as a vector of (dim, tag) pairs) 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
    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)
  end subroutine gmshModelGeoTranslate

  !> Rotate the entities `dimTags' (given as a vector of (dim, tag) pairs) 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
    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)
  end subroutine gmshModelGeoRotate

  !> Scale the entities `dimTags' (given as a vector of (dim, tag) pairs) 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
    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)
  end subroutine gmshModelGeoDilate

  !> Mirror the entities `dimTags' (given as a vector of (dim, tag) pairs) 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
    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)
  end subroutine gmshModelGeoMirror

  !> Mirror the entities `dimTags' (given as a vector of (dim, tag) pairs) 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
    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)
  end subroutine gmshModelGeoSymmetrize

  !> Copy the entities `dimTags' (given as a vector of (dim, tag) pairs) 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
    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)
    outDimTags = ovectorpair_(api_outDimTags_, &
      api_outDimTags_n_)
  end subroutine gmshModelGeoCopy

  !> Remove the entities `dimTags' (given as a vector of (dim, tag) pairs) 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
    call C_API(api_dimTags_=dimTags, &
         api_dimTags_n_=size_gmsh_pair(dimTags), &
         recursive=optval_c_bool(.false., recursive), &
         ierr_=ierr)
  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
    call C_API(ierr_=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, &
                                    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
    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)
    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
    gmshModelGeoGetMaxTag = C_API(dim=int(dim, c_int), &
                            ierr_=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)
    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
    call C_API(dim=int(dim, c_int), &
         maxTag=int(maxTag, c_int), &
         ierr_=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, &
                                        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
    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)
  end function gmshModelGeoAddPhysicalGroup

  !> Remove the physical groups `dimTags' (given as a vector of (dim, tag)
  !! pairs) 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
    call C_API(api_dimTags_=dimTags, &
         api_dimTags_n_=size_gmsh_pair(dimTags), &
         ierr_=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)
    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
    call C_API(ierr_=ierr)
  end subroutine gmshModelGeoSynchronize

  !> Set a mesh size constraint on the entities `dimTags' (given as a vector of
  !! (dim, tag) pairs) 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
    call C_API(api_dimTags_=dimTags, &
         api_dimTags_n_=size_gmsh_pair(dimTags), &
         size=real(size, c_double), &
         ierr_=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)
    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
    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)
  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
    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)
  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
    call C_API(tag=int(tag, c_int), &
         api_cornerTags_=cornerTags, &
         api_cornerTags_n_=size_gmsh_int(cornerTags), &
         ierr_=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)
    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
    call C_API(dim=int(dim, c_int), &
         tag=int(tag, c_int), &
         angle=optval_c_double(45., angle), &
         ierr_=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)
    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
    call C_API(dim=int(dim, c_int), &
         tag=int(tag, c_int), &
         val=int(val, c_int), &
         ierr_=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)
    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
    call C_API(dim=int(dim, c_int), &
         tag=int(tag, c_int), &
         val=optval_c_bool(.true., val), &
         ierr_=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)
    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
    call C_API(dim=int(dim, c_int), &
         tag=int(tag, c_int), &
         val=int(val, c_int), &
         ierr_=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)
    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
    call C_API(dim=int(dim, c_int), &
         tag=int(tag, c_int), &
         val=int(val, c_int), &
         ierr_=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)
    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
    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)
  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
    gmshModelOccAddLine = C_API(startTag=int(startTag, c_int), &
                          endTag=int(endTag, c_int), &
                          tag=optval_c_int(-1, tag), &
                          ierr_=ierr)
  end function gmshModelOccAddLine

  !> Add a circle arc in the OpenCASCADE CAD representation, between the two
  !! points with tags `startTag' and `endTag', with middle point `middleTag'. If
  !! `center' is true, the middle point is the center of the circle; otherwise
  !! the circle goes through the middle point. 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, &
                                    middleTag, &
                                    endTag, &
                                    tag, &
                                    center, &
                                    ierr)
    interface
    function C_API(startTag, &
                   middleTag, &
                   endTag, &
                   tag, &
                   center, &
                   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) :: middleTag
      integer(c_int), value, intent(in) :: endTag
      integer(c_int), value, intent(in) :: tag
      integer(c_int), value, intent(in) :: center
      integer(c_int), intent(out), optional :: ierr_
    end function C_API
    end interface
    integer(c_int) :: gmshModelOccAddCircleArc
    integer, intent(in) :: startTag
    integer, intent(in) :: middleTag
    integer, intent(in) :: endTag
    integer, intent(in), optional :: tag
    logical, intent(in), optional :: center
    integer(c_int), intent(out), optional :: ierr
    gmshModelOccAddCircleArc = C_API(startTag=int(startTag, c_int), &
                               middleTag=int(middleTag, c_int), &
                               endTag=int(endTag, c_int), &
                               tag=optval_c_int(-1, tag), &
                               center=optval_c_bool(.true., center), &
                               ierr_=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, &
                                 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
    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)
  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
    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)
  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
    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)
  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. If the `tangents' vector contains 6 entries, use them as
  !! concatenated x, y, z components of the initial and final tangents of the
  !! b-spline; if it contains 3 times as many entries as the number of points,
  !! use them as concatenated x, y, z components of the tangents at each point,
  !! unless the norm of the tangent is zero.
  function gmshModelOccAddSpline(pointTags, &
                                 tag, &
                                 tangents, &
                                 ierr)
    interface
    function C_API(api_pointTags_, &
                   api_pointTags_n_, &
                   tag, &
                   api_tangents_, &
                   api_tangents_n_, &
                   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
      real(c_double), dimension(*), optional :: api_tangents_
      integer(c_size_t), value, intent(in) :: api_tangents_n_
      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
    real(c_double), dimension(:), intent(in), optional :: tangents
    integer(c_int), intent(out), optional :: ierr
    gmshModelOccAddSpline = C_API(api_pointTags_=pointTags, &
                            api_pointTags_n_=size_gmsh_int(pointTags), &
                            tag=optval_c_int(-1, tag), &
                            api_tangents_=tangents, &
                            api_tangents_n_=size_gmsh_double(tangents), &
                            ierr_=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, &
                                  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
    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)
  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
    gmshModelOccAddBezier = C_API(api_pointTags_=pointTags, &
                            api_pointTags_n_=size_gmsh_int(pointTags), &
                            tag=optval_c_int(-1, tag), &
                            ierr_=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, &
                               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
    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)
  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
    gmshModelOccAddCurveLoop = C_API(api_curveTags_=curveTags, &
                               api_curveTags_n_=size_gmsh_int(curveTags), &
                               tag=optval_c_int(-1, tag), &
                               ierr_=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)
    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
    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)
  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
    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)
  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
    gmshModelOccAddPlaneSurface = C_API(api_wireTags_=wireTags, &
                                  api_wireTags_n_=size_gmsh_int(wireTags), &
                                  tag=optval_c_int(-1, tag), &
                                  ierr_=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, &
                                         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
    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(2, 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)
  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
    gmshModelOccAddBSplineFilling = C_API(wireTag=int(wireTag, c_int), &
                                    tag=optval_c_int(-1, tag), &
                                    type=istring_(optval_c_str("", type)), &
                                    ierr_=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)
    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
    gmshModelOccAddBezierFilling = C_API(wireTag=int(wireTag, c_int), &
                                   tag=optval_c_int(-1, tag), &
                                   type=istring_(optval_c_str("", type)), &
                                   ierr_=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, &
                                         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
    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)
  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
    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)
  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
    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)
  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
    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)
  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
    gmshModelOccAddVolume = C_API(api_shellTags_=shellTags, &
                            api_shellTags_n_=size_gmsh_int(shellTags), &
                            tag=optval_c_int(-1, tag), &
                            ierr_=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)
    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
    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)
  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
    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)
  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
    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)
  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
    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)
  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
    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)
  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
    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)
  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' as a vector of (dim, tag) pairs. 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
    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)
    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
    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)
    outDimTags = ovectorpair_(api_outDimTags_, &
      api_outDimTags_n_)
  end subroutine gmshModelOccAddThickSolid

  !> Extrude the entities `dimTags' (given as a vector of (dim, tag) pairs) in
  !! the OpenCASCADE CAD representation, using a translation along (`dx', `dy',
  !! `dz'). Return extruded entities in `outDimTags'. If the `numElements'
  !! vector is not empty, also extrude the mesh: the entries in `numElements'
  !! give the number of elements in each layer. If the `height' vector 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
    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)
    outDimTags = ovectorpair_(api_outDimTags_, &
      api_outDimTags_n_)
  end subroutine gmshModelOccExtrude

  !> Extrude the entities `dimTags' (given as a vector of (dim, tag) pairs) 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
  !! the `numElements' vector is not empty, also extrude the mesh: the entries
  !! in `numElements' give the number of elements in each layer. If the `height'
  !! vector 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
    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)
    outDimTags = ovectorpair_(api_outDimTags_, &
      api_outDimTags_n_)
  end subroutine gmshModelOccRevolve

  !> Add a pipe in the OpenCASCADE CAD representation, by extruding the entities
  !! `dimTags' (given as a vector of (dim, tag) pairs) 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
    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)
    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' as a vector of (dim, tag)
  !! pairs. 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
    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)
    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
    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)
    outDimTags = ovectorpair_(api_outDimTags_, &
      api_outDimTags_n_)
  end subroutine gmshModelOccChamfer

  !> Defeature the volumes `volumeTags' by removing the surfaces `surfaceTags'.
  !! Return the defeatured entities in `outDimTags'. Remove the original volume
  !! if `removeVolume' is set.
  subroutine gmshModelOccDefeature(volumeTags, &
                                   surfaceTags, &
                                   outDimTags, &
                                   removeVolume, &
                                   ierr)
    interface
    subroutine C_API(api_volumeTags_, &
                     api_volumeTags_n_, &
                     api_surfaceTags_, &
                     api_surfaceTags_n_, &
                     api_outDimTags_, &
                     api_outDimTags_n_, &
                     removeVolume, &
                     ierr_) &
      bind(C, name="gmshModelOccDefeature")
      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_surfaceTags_
      integer(c_size_t), value, intent(in) :: api_surfaceTags_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) :: surfaceTags
    integer(c_int), dimension(:,:), allocatable, intent(out) :: outDimTags
    logical, intent(in), optional :: removeVolume
    integer(c_int), intent(out), optional :: ierr
    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_surfaceTags_=surfaceTags, &
         api_surfaceTags_n_=size_gmsh_int(surfaceTags), &
         api_outDimTags_=api_outDimTags_, &
         api_outDimTags_n_=api_outDimTags_n_, &
         removeVolume=optval_c_bool(.true., removeVolume), &
         ierr_=ierr)
    outDimTags = ovectorpair_(api_outDimTags_, &
      api_outDimTags_n_)
  end subroutine gmshModelOccDefeature

  !> Create a fillet edge between edges `edgeTag1' and `edgeTag2' with radius
  !! `radius'. The modifed edges keep their tag. If `tag' is positive, set the
  !! tag explicitly; otherwise a new tag is selected automatically.
  function gmshModelOccFillet2D(edgeTag1, &
                                edgeTag2, &
                                radius, &
                                tag, &
                                ierr)
    interface
    function C_API(edgeTag1, &
                   edgeTag2, &
                   radius, &
                   tag, &
                   ierr_) &
      bind(C, name="gmshModelOccFillet2D")
      use, intrinsic :: iso_c_binding
      integer(c_int) :: C_API
      integer(c_int), value, intent(in) :: edgeTag1
      integer(c_int), value, intent(in) :: edgeTag2
      real(c_double), value, intent(in) :: radius
      integer(c_int), value, intent(in) :: tag
      integer(c_int), intent(out), optional :: ierr_
    end function C_API
    end interface
    integer(c_int) :: gmshModelOccFillet2D
    integer, intent(in) :: edgeTag1
    integer, intent(in) :: edgeTag2
    real(c_double), intent(in) :: radius
    integer, intent(in), optional :: tag
    integer(c_int), intent(out), optional :: ierr
    gmshModelOccFillet2D = C_API(edgeTag1=int(edgeTag1, c_int), &
                           edgeTag2=int(edgeTag2, c_int), &
                           radius=real(radius, c_double), &
                           tag=optval_c_int(-1, tag), &
                           ierr_=ierr)
  end function gmshModelOccFillet2D

  !> Create a chamfer edge between edges `edgeTag1' and `edgeTag2' with
  !! distance1 `distance1' and distance2 `distance2'. The modifed edges keep
  !! their tag. If `tag' is positive, set the tag explicitly; otherwise a new
  !! tag is selected automatically.
  function gmshModelOccChamfer2D(edgeTag1, &
                                 edgeTag2, &
                                 distance1, &
                                 distance2, &
                                 tag, &
                                 ierr)
    interface
    function C_API(edgeTag1, &
                   edgeTag2, &
                   distance1, &
                   distance2, &
                   tag, &
                   ierr_) &
      bind(C, name="gmshModelOccChamfer2D")
      use, intrinsic :: iso_c_binding
      integer(c_int) :: C_API
      integer(c_int), value, intent(in) :: edgeTag1
      integer(c_int), value, intent(in) :: edgeTag2
      real(c_double), value, intent(in) :: distance1
      real(c_double), value, intent(in) :: distance2
      integer(c_int), value, intent(in) :: tag
      integer(c_int), intent(out), optional :: ierr_
    end function C_API
    end interface
    integer(c_int) :: gmshModelOccChamfer2D
    integer, intent(in) :: edgeTag1
    integer, intent(in) :: edgeTag2
    real(c_double), intent(in) :: distance1
    real(c_double), intent(in) :: distance2
    integer, intent(in), optional :: tag
    integer(c_int), intent(out), optional :: ierr
    gmshModelOccChamfer2D = C_API(edgeTag1=int(edgeTag1, c_int), &
                            edgeTag2=int(edgeTag2, c_int), &
                            distance1=real(distance1, c_double), &
                            distance2=real(distance2, c_double), &
                            tag=optval_c_int(-1, tag), &
                            ierr_=ierr)
  end function gmshModelOccChamfer2D

  !> Create an offset curve based on the curve loop `curveLoopTag' with offset
  !! `offset'. Return the offset curves in `outDimTags' as a vector of (dim,
  !! tag) pairs.
  subroutine gmshModelOccOffsetCurve(curveLoopTag, &
                                     offset, &
                                     outDimTags, &
                                     ierr)
    interface
    subroutine C_API(curveLoopTag, &
                     offset, &
                     api_outDimTags_, &
                     api_outDimTags_n_, &
                     ierr_) &
      bind(C, name="gmshModelOccOffsetCurve")
      use, intrinsic :: iso_c_binding
      integer(c_int), value, intent(in) :: curveLoopTag
      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), intent(out), optional :: ierr_
    end subroutine C_API
    end interface
    integer, intent(in) :: curveLoopTag
    real(c_double), intent(in) :: offset
    integer(c_int), dimension(:,:), allocatable, intent(out) :: outDimTags
    integer(c_int), intent(out), optional :: ierr
    type(c_ptr) :: api_outDimTags_
    integer(c_size_t) :: api_outDimTags_n_
    call C_API(curveLoopTag=int(curveLoopTag, c_int), &
         offset=real(offset, c_double), &
         api_outDimTags_=api_outDimTags_, &
         api_outDimTags_n_=api_outDimTags_n_, &
         ierr_=ierr)
    outDimTags = ovectorpair_(api_outDimTags_, &
      api_outDimTags_n_)
  end subroutine gmshModelOccOffsetCurve

  !> Find the minimal distance between shape with `dim1' and `tag1' and shape
  !! with `dim2' and `tag2' and the according coordinates. Return the distance
  !! in `distance' and the coordinate of the points as `x1', `y1', `z1' and
  !! `x2', `y2', `z2'.
  subroutine gmshModelOccGetDistance(dim1, &
                                     tag1, &
                                     dim2, &
                                     tag2, &
                                     distance, &
                                     x1, &
                                     y1, &
                                     z1, &
                                     x2, &
                                     y2, &
                                     z2, &
                                     ierr)
    interface
    subroutine C_API(dim1, &
                     tag1, &
                     dim2, &
                     tag2, &
                     distance, &
                     x1, &
                     y1, &
                     z1, &
                     x2, &
                     y2, &
                     z2, &
                     ierr_) &
      bind(C, name="gmshModelOccGetDistance")
      use, intrinsic :: iso_c_binding
      integer(c_int), value, intent(in) :: dim1
      integer(c_int), value, intent(in) :: tag1
      integer(c_int), value, intent(in) :: dim2
      integer(c_int), value, intent(in) :: tag2
      real(c_double) :: distance
      real(c_double) :: x1
      real(c_double) :: y1
      real(c_double) :: z1
      real(c_double) :: x2
      real(c_double) :: y2
      real(c_double) :: z2
      integer(c_int), intent(out), optional :: ierr_
    end subroutine C_API
    end interface
    integer, intent(in) :: dim1
    integer, intent(in) :: tag1
    integer, intent(in) :: dim2
    integer, intent(in) :: tag2
    real(c_double) :: distance
    real(c_double) :: x1
    real(c_double) :: y1
    real(c_double) :: z1
    real(c_double) :: x2
    real(c_double) :: y2
    real(c_double) :: z2
    integer(c_int), intent(out), optional :: ierr
    call C_API(dim1=int(dim1, c_int), &
         tag1=int(tag1, c_int), &
         dim2=int(dim2, c_int), &
         tag2=int(tag2, c_int), &
         distance=distance, &
         x1=x1, &
         y1=y1, &
         z1=z1, &
         x2=x2, &
         y2=y2, &
         z2=z2, &
         ierr_=ierr)
  end subroutine gmshModelOccGetDistance

  !> Compute the boolean union (the fusion) of the entities `objectDimTags' and
  !! `toolDimTags' (vectors of (dim, tag) pairs) 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
    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)
    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' (vectors of (dim, tag) pairs) 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
    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)
    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' (given as vectors of (dim, tag) pairs) 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
    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)
    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' (given as
  !! vectors of (dim, tag) pairs) in the OpenCASCADE CAD representation, making
  !! all interfaces 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
    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)
    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' (given as a vector of (dim, tag) pairs) 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
    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)
  end subroutine gmshModelOccTranslate

  !> Rotate the entities `dimTags' (given as a vector of (dim, tag) pairs) 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
    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)
  end subroutine gmshModelOccRotate

  !> Scale the entities `dimTags' (given as a vector of (dim, tag) pairs) 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
    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)
  end subroutine gmshModelOccDilate

  !> Mirror the entities `dimTags' (given as a vector of (dim, tag) pairs) 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
    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)
  end subroutine gmshModelOccMirror

  !> Mirror the entities `dimTags' (given as a vector of (dim, tag) pairs) 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
    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)
  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' (given as a vector of (dim, tag) pairs) 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
    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)
  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
    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)
    outDimTags = ovectorpair_(api_outDimTags_, &
      api_outDimTags_n_)
  end subroutine gmshModelOccCopy

  !> Remove the entities `dimTags' (given as a vector of (dim, tag) pairs) 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
    call C_API(api_dimTags_=dimTags, &
         api_dimTags_n_=size_gmsh_pair(dimTags), &
         recursive=optval_c_bool(.false., recursive), &
         ierr_=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)
    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
    call C_API(ierr_=ierr)
  end subroutine gmshModelOccRemoveAllDuplicates

  !> Apply various healing procedures to the entities `dimTags' (given as a
  !! vector of (dim, tag) pairs), 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
    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)
    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
    call C_API(api_dimTags_=dimTags, &
         api_dimTags_n_=size_gmsh_pair(dimTags), &
         ierr_=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', as a vector of (dim, tag) pairs. 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
    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)
    outDimTags = ovectorpair_(api_outDimTags_, &
      api_outDimTags_n_)
  end subroutine gmshModelOccImportShapes

  !> Import 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' as a vector of (dim, tag)
  !! pairs. 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
    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)
    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) 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
    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)
    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, &
                                                  dimTags, &
                                                  dim, &
                                                  ierr)
    interface
    subroutine C_API(xmin, &
                     ymin, &
                     zmin, &
                     xmax, &
                     ymax, &
                     zmax, &
                     api_dimTags_, &
                     api_dimTags_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_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
    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) :: dimTags
    integer, intent(in), optional :: dim
    integer(c_int), intent(out), optional :: ierr
    type(c_ptr) :: api_dimTags_
    integer(c_size_t) :: api_dimTags_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_dimTags_=api_dimTags_, &
         api_dimTags_n_=api_dimTags_n_, &
         dim=optval_c_int(-1, dim), &
         ierr_=ierr)
    dimTags = ovectorpair_(api_dimTags_, &
      api_dimTags_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
    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)
  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
    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)
    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
    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)
    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'. If
  !! no density is attached to the entity (the default), the value corresponds
  !! respectively to the length, area and volume for `dim' = 1, 2 and 3.
  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
    call C_API(dim=int(dim, c_int), &
         tag=int(tag, c_int), &
         mass=mass, &
         ierr_=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)
    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
    call C_API(dim=int(dim, c_int), &
         tag=int(tag, c_int), &
         x=x, &
         y=y, &
         z=z, &
         ierr_=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, &
                                            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
    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)
    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
    gmshModelOccGetMaxTag = C_API(dim=int(dim, c_int), &
                            ierr_=ierr)
  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
    call C_API(dim=int(dim, c_int), &
         maxTag=int(maxTag, c_int), &
         ierr_=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)
    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
    call C_API(ierr_=ierr)
  end subroutine gmshModelOccSynchronize

  !> Set a mesh size constraint on the entities `dimTags' (given as a vector of
  !! (dim, tag) pairs) 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
    call C_API(api_dimTags_=dimTags, &
         api_dimTags_n_=size_gmsh_pair(dimTags), &
         size=real(size, c_double), &
         ierr_=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)
    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
    gmshViewAdd = C_API(name=istring_(name), &
                  tag=optval_c_int(-1, tag), &
                  ierr_=ierr)
  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
    call C_API(tag=int(tag, c_int), &
         ierr_=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)
    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
    gmshViewGetIndex = C_API(tag=int(tag, c_int), &
                       ierr_=ierr)
  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
    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)
    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
    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)
  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
    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)
  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
      type(c_ptr), intent(out) :: 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
    type(c_ptr) :: api_dataType_
    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_=api_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)
    dataType = ostring_(api_dataType_)
    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
      type(c_ptr), intent(out) :: 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
    type(c_ptr) :: api_dataType_
    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_=api_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)
    dataType = ostring_(api_dataType_)
    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
    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)
  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. If `returnAdaptive' is set, return
  !! the data obtained after adaptive refinement, if available.
  subroutine gmshViewGetListData(tag, &
                                 dataType, &
                                 numElements, &
                                 data, &
                                 data_n, &
                                 returnAdaptive, &
                                 ierr)
    interface
    subroutine C_API(tag, &
                     api_dataType_, &
                     api_dataType_n_, &
                     api_numElements_, &
                     api_numElements_n_, &
                     api_data_, &
                     api_data_n_, &
                     api_data_nn_, &
                     returnAdaptive, &
                     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), value, intent(in) :: returnAdaptive
      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
    logical, intent(in), optional :: returnAdaptive
    integer(c_int), intent(out), optional :: ierr
    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_, &
         returnAdaptive=optval_c_bool(.false., returnAdaptive), &
         ierr_=ierr)
    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
    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)
  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
    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)
    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
    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)
  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
    gmshViewAddAlias = C_API(refTag=int(refTag, c_int), &
                       copyOptions=optval_c_bool(.false., copyOptions), &
                       tag=optval_c_int(-1, tag), &
                       ierr_=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)
    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
    call C_API(what=istring_(what), &
         how=istring_(how), &
         remove=optval_c_bool(.true., remove), &
         copyOptions=optval_c_bool(.true., copyOptions), &
         ierr_=ierr)
  end subroutine gmshViewCombine

  !> Probe the view `tag' for its `values' 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 `values' 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, &
                           values, &
                           distance, &
                           step, &
                           numComp, &
                           gradient, &
                           distanceMax, &
                           xElemCoord, &
                           yElemCoord, &
                           zElemCoord, &
                           dim, &
                           ierr)
    interface
    subroutine C_API(tag, &
                     x, &
                     y, &
                     z, &
                     api_values_, &
                     api_values_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_values_
      integer(c_size_t) :: api_values_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) :: values
    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
    type(c_ptr) :: api_values_
    integer(c_size_t) :: api_values_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_values_=api_values_, &
         api_values_n_=api_values_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)
    values = ovectordouble_(api_values_, &
      api_values_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
    call C_API(tag=int(tag, c_int), &
         fileName=istring_(fileName), &
         append=optval_c_bool(.false., append), &
         ierr_=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)
    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
    call C_API(tag=int(tag, c_int), &
         value=int(value, c_int), &
         windowIndex=optval_c_int(0, windowIndex), &
         ierr_=ierr)
  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
    call C_API(tag=int(tag, c_int), &
         name=istring_(name), &
         value=real(value, c_double), &
         ierr_=ierr)
  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
    call C_API(tag=int(tag, c_int), &
         name=istring_(name), &
         value=value, &
         ierr_=ierr)
  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
    call C_API(tag=int(tag, c_int), &
         name=istring_(name), &
         value=istring_(value), &
         ierr_=ierr)
  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
      type(c_ptr), intent(out) :: 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
    type(c_ptr) :: api_value_
    call C_API(tag=int(tag, c_int), &
         name=istring_(name), &
         api_value_=api_value_, &
         ierr_=ierr)
    value = ostring_(api_value_)
  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
    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)
  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
    call C_API(tag=int(tag, c_int), &
         name=istring_(name), &
         r=r, &
         g=g, &
         b=b, &
         a=a, &
         ierr_=ierr)
  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
    call C_API(refTag=int(refTag, c_int), &
         tag=int(tag, c_int), &
         ierr_=ierr)
  end subroutine gmshViewOptionCopy

  !> Set the numerical option `option' to the value `value' for plugin `name'.
  !! Plugins available in the official Gmsh release are listed in the "Gmsh
  !! plugins" chapter of the Gmsh reference manual
  !! (https://gmsh.info/doc/texinfo/gmsh.html#Gmsh-plugins).
  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
    call C_API(name=istring_(name), &
         option=istring_(option), &
         value=real(value, c_double), &
         ierr_=ierr)
  end subroutine gmshPluginSetNumber

  !> Set the string option `option' to the value `value' for plugin `name'.
  !! Plugins available in the official Gmsh release are listed in the "Gmsh
  !! plugins" chapter of the Gmsh reference manual
  !! (https://gmsh.info/doc/texinfo/gmsh.html#Gmsh-plugins).
  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
    call C_API(name=istring_(name), &
         option=istring_(option), &
         value=istring_(value), &
         ierr_=ierr)
  end subroutine gmshPluginSetString

  !> Run the plugin `name'. Return the tag of the created view (if any). Plugins
  !! available in the official Gmsh release are listed in the "Gmsh plugins"
  !! chapter of the Gmsh reference manual
  !! (https://gmsh.info/doc/texinfo/gmsh.html#Gmsh-plugins).
  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
    gmshPluginRun = C_API(name=istring_(name), &
                    ierr_=ierr)
  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
    call C_API(ierr_=ierr)
  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
    call C_API(ierr_=ierr)
  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
    call C_API(ierr_=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)
    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
    call C_API(time=optval_c_double(-1., time), &
         ierr_=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)
    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
    call C_API(ierr_=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)
    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
    call C_API(action=istring_(optval_c_str("", action)), &
         ierr_=ierr)
  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
    call C_API(ierr_=ierr)
  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
    call C_API(ierr_=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)
    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
    call C_API(ierr_=ierr)
  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
    gmshFltkIsAvailable = C_API(ierr_=ierr)
  end function gmshFltkIsAvailable

  !> Select entities in the user interface. Return the selected entities as a
  !! vector of (dim, tag) pairs. 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
    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)
    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
    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)
    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
    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)
    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
    call C_API(how=istring_(optval_c_str("v", how)), &
         ratio=optval_c_double(0.5, ratio), &
         ierr_=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)
    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
    call C_API(windowIndex=optval_c_int(0, windowIndex), &
         ierr_=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)
    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
    call C_API(message=istring_(message), &
         graphics=optval_c_bool(.false., graphics), &
         ierr_=ierr)
  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
    call C_API(dim=int(dim, c_int), &
         tag=int(tag, c_int), &
         ierr_=ierr)
  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
    call C_API(name=istring_(name), &
         ierr_=ierr)
  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
    call C_API(name=istring_(name), &
         ierr_=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, &
                                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
    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)
    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
    call C_API(name=istring_(name), &
         api_value_=value, &
         api_value_n_=size_gmsh_double(value), &
         ierr_=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, &
                                 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
    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)
  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
    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)
    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
    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)
    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
    call C_API(name=istring_(optval_c_str("", name)), &
         ierr_=ierr)
  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
    call C_API(fileName=istring_(fileName), &
         ierr_=ierr)
  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
    call C_API(data=istring_(data), &
         format=istring_(optval_c_str("json", format)), &
         ierr_=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)
    interface
    subroutine C_API(api_data_, &
                     name, &
                     format, &
                     ierr_) &
      bind(C, name="gmshOnelabGet")
      use, intrinsic :: iso_c_binding
      type(c_ptr), intent(out) :: 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
    type(c_ptr) :: api_data_
    call C_API(api_data_=api_data_, &
         name=istring_(optval_c_str("", name)), &
         format=istring_(optval_c_str("json", format)), &
         ierr_=ierr)
    data = ostring_(api_data_)
  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
    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)
    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
    call C_API(name=istring_(name), &
         api_value_=value, &
         api_value_n_=size_gmsh_double(value), &
         ierr_=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, &
                                 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
    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)
  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
    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)
    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
    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)
    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
    gmshOnelabGetChanged = C_API(name=istring_(name), &
                           ierr_=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)
    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
    call C_API(name=istring_(name), &
         value=int(value, c_int), &
         ierr_=ierr)
  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
    call C_API(name=istring_(optval_c_str("", name)), &
         ierr_=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)
    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
    call C_API(name=istring_(optval_c_str("", name)), &
         command=istring_(optval_c_str("", command)), &
         ierr_=ierr)
  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
    call C_API(message=istring_(message), &
         level=istring_(optval_c_str("info", level)), &
         ierr_=ierr)
  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
    call C_API(ierr_=ierr)
  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
    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)
    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
    call C_API(ierr_=ierr)
  end subroutine gmshLoggerStop

  !> Return wall clock time (in s).
  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
    gmshLoggerGetWallTime = C_API(ierr_=ierr)
  end function gmshLoggerGetWallTime

  !> Return CPU time (in s).
  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
    gmshLoggerGetCpuTime = C_API(ierr_=ierr)
  end function gmshLoggerGetCpuTime

  !> Return memory usage (in Mb).
  function gmshLoggerGetMemory(ierr)
    interface
    function C_API(ierr_) &
      bind(C, name="gmshLoggerGetMemory")
      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) :: gmshLoggerGetMemory
    integer(c_int), intent(out), optional :: ierr
    gmshLoggerGetMemory = C_API(ierr_=ierr)
  end function gmshLoggerGetMemory

  !> Return total available memory (in Mb).
  function gmshLoggerGetTotalMemory(ierr)
    interface
    function C_API(ierr_) &
      bind(C, name="gmshLoggerGetTotalMemory")
      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) :: gmshLoggerGetTotalMemory
    integer(c_int), intent(out), optional :: ierr
    gmshLoggerGetTotalMemory = C_API(ierr_=ierr)
  end function gmshLoggerGetTotalMemory

  !> 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
      type(c_ptr), intent(out) :: 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
    type(c_ptr) :: api_error_
    call C_API(api_error_=api_error_, &
         ierr_=ierr)
    error = ostring_(api_error_)
  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 ostring_(cptr) result(v)
    type(c_ptr), intent(inout) :: cptr
    character(len=:), allocatable :: v
    character(len=GMSH_API_MAX_STR_LEN), pointer :: fptr
    integer(c_size_t) :: i
    call c_f_pointer(cptr, fptr)
    do i = 1_c_size_t, GMSH_API_MAX_STR_LEN
      if (fptr(i:i) == c_null_char) exit
    end do
    v = fptr(:i)
    call gmshFree(cptr)
  end function ostring_

  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
    type(c_array_t), pointer :: c_array(:)
    character(len=GMSH_API_MAX_STR_LEN), pointer :: fptr

    call c_f_pointer(cptr, c_array, [n])
    allocate(v(n))
    do i = 1_c_size_t, n
      v(i) = ostring_(c_array(i)%s)
    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:istart + iend - 1) = 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:istart + iend - 1) = 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:istart + iend - 1) = 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:istart + iend - 1) = 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_

end module gmsh
