diff --git a/contrib/hxt/CMakeLists.txt b/contrib/hxt/CMakeLists.txt
index cfbbe652bbc1039879fdfbcbe71138fae6702aeb..d69f0a0cce9d4b9855cb7e90a046ff09cfc626cf 100644
--- a/contrib/hxt/CMakeLists.txt
+++ b/contrib/hxt/CMakeLists.txt
@@ -11,7 +11,10 @@
 # Fixme: HXT should rather be included using simple target_link_library calls,
 # as for external libraries
 
-# === HXT core
+
+#################################################################################
+# HXT core
+#################################################################################
 set(SRC
     hxt_bbox.c
     hxt_mesh.c
@@ -34,7 +37,10 @@ list(APPEND HXT_INC_DIRS
      contrib/hxt/core/src
      contrib/hxt/core/include)
 
-# === HXT reparam
+
+#################################################################################
+# HXT reparam
+#################################################################################
 set(SRC
     hxt_class_macro.h
     hxt_curvature.c
@@ -62,13 +68,19 @@ list(APPEND HXT_INC_DIRS
      contrib/hxt/reparam/src
      contrib/hxt/reparam/include)
 
-# === HXT sizeField
+
+#################################################################################
+# HXT sizeField
+#################################################################################
 if(HAVE_P4EST)
   append_gmsh_src(contrib/hxt/sizeField "hxt_octree.cpp;hxt_octree.h" )
   list(APPEND HXT_INC_DIRS contrib/hxt/sizeField)
 endif()
 
-# === HXT predicates
+
+#################################################################################
+# HXT predicates
+#################################################################################
 # do not use arithmetic contraction in predicates.c
 if(MSVC OR (CMAKE_C_COMPILER_ID STREQUAL "Intel" AND WIN32))
   set_source_files_properties("${CMAKE_CURRENT_SOURCE_DIR}/predicates/src/predicates.c"
@@ -93,7 +105,9 @@ list(APPEND HXT_INC_DIRS
      contrib/hxt/predicates/include)
 
 
-# === HXT tetBR
+#################################################################################
+# HXT tetBR
+#################################################################################
 append_gmsh_src(contrib/hxt/tetBR/src hxt_boundary_recovery.cxx)
 append_gmsh_src(contrib/hxt/tetBR/include hxt_boundary_recovery.h)
 list(APPEND HXT_INC_DIRS
@@ -101,30 +115,56 @@ list(APPEND HXT_INC_DIRS
      contrib/hxt/tetBR/include)
 
 
-# === HXT tetMesh
+#################################################################################
+# HXT tetMesh
+#################################################################################
 set(SRC
     hxt_edgeRemoval.c
+    hxt_edgeRemoval.h
     hxt_smoothing.c
+    hxt_smoothing.h
     HXTSPR.c
+    HXTSPR.h
     hxt_tetColor.c
+    hxt_tetColor.h
     hxt_tetDelaunay.c
     hxt_tetFlag.c
     hxt_tetMesh.c
     hxt_tetNodalSize.c
+    hxt_tetNodalSize.h
     hxt_tetOpti.c
+    hxt_tetOptiUtils.h
+    hxt_tetPartition.h
     hxt_tetQuality.c
+    hxt_tetQuality.h
     hxt_tetRefine.c
+    hxt_tetRefine.h
     hxt_tetRepair.c
     hxt_tetSync.c
+    hxt_tetSync.h
     hxt_tetUtils.c
+    hxt_tetUtils.h
     hxt_vertices.c
    )
 
+set(INC
+    hxt_tetDelaunay.h
+    hxt_tetFlag.h
+    hxt_tetMesh.h
+    hxt_tetOpti.h
+    hxt_tetRepair.h
+    hxt_vertices.h
+   )
+
 append_gmsh_src(contrib/hxt/tetMesh/src "${SRC}")
-append_gmsh_src(contrib/hxt/tetMesh/include hxt_tetMesh.h)
+append_gmsh_src(contrib/hxt/tetMesh/include "${INC}")
+
 list(APPEND HXT_INC_DIRS
      contrib/hxt/tetMesh/src
      contrib/hxt/tetMesh/include)
 
-# this variable should be available in the parent CMakeLists
+
+#################################################################################
+# propagate HXT_INC_DIRS to parent CMakeLists
+#################################################################################
 set(HXT_INC_DIRS ${HXT_INC_DIRS} PARENT_SCOPE)
diff --git a/contrib/hxt/core/CMakeLists.txt b/contrib/hxt/core/CMakeLists.txt
index d88337ed53339f682ad35b4509afeb9f1ebd1045..7d85959ecf16a0025612468468df8db4c52b8fc2 100644
--- a/contrib/hxt/core/CMakeLists.txt
+++ b/contrib/hxt/core/CMakeLists.txt
@@ -1,25 +1,36 @@
 cmake_minimum_required(VERSION 3.9)
 project(hxt_core C)
 
+# include guard for CMake:
+# if you plan to include multiple directory that depend on this one,
+# you need to include this directory first
 if(TARGET hxt_core)
-  # header guard for CMake. You need to include this directory first
   return()
 endif()
 
+
+#################################################################################
+# Options
+#################################################################################
 option(HXT_ENABLE_OPENMP "Enable OpenMP" ON)
 option(HXT_ALIGN_ALLOCATIONS "Align allocation" OFF)
-option(HXT_CORE_FILEIO "Compile HXT core with file I/O" OFF)
 option(HXT_CORE_OBJECT_ONLY "Do not create hxt_core library" ON)
 
+
+#################################################################################
+# Library definition
+#################################################################################
 set(HXT_CORE_SRC
     "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_bbox.c"
     "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_mesh.c"
     "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_message.c"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_opt.c"
     "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_sort.c"
     "${CMAKE_CURRENT_SOURCE_DIR}/include/hxt_bbox.h"
     "${CMAKE_CURRENT_SOURCE_DIR}/include/hxt_mesh.h"
     "${CMAKE_CURRENT_SOURCE_DIR}/include/hxt_message.h"
     "${CMAKE_CURRENT_SOURCE_DIR}/include/hxt_omp.h"
+    "${CMAKE_CURRENT_SOURCE_DIR}/include/hxt_opt.h"
     "${CMAKE_CURRENT_SOURCE_DIR}/include/hxt_sort.h"
     "${CMAKE_CURRENT_SOURCE_DIR}/include/hxt_tools.h"
    )
@@ -30,7 +41,6 @@ if(HXT_CORE_OBJECT_ONLY)
 else()
   add_library(hxt_core ${HXT_CORE_SRC})
 endif()
-
 target_include_directories(hxt_core PUBLIC include)
 target_compile_features(hxt_core PRIVATE c_std_99)
 
@@ -41,10 +51,10 @@ if(HXT_ENABLE_OPENMP)
   endif()
 endif()
 
+
+#################################################################################
+# Compilation flags corresponding to options
+#################################################################################
 if(HXT_ALIGN_ALLOCATIONS)
 	target_compile_definitions(hxt_core PUBLIC HXT_ALIGN_ALLOCATIONS)
 endif()
-
-if(HXT_ENABLE_FILEIO)
-	target_compile_definitions(hxt_core PUBLIC HXT_CORE_FILEIO)
-endif()
diff --git a/contrib/hxt/core/include/hxt_mesh.h b/contrib/hxt/core/include/hxt_mesh.h
index 46134e32743bd42d60c341e760a124bf5247c28e..9616c5fd3ca5d1e419bf4e228a1d7addf3a09b44 100644
--- a/contrib/hxt/core/include/hxt_mesh.h
+++ b/contrib/hxt/core/include/hxt_mesh.h
@@ -134,10 +134,10 @@ typedef struct {
 HXTStatus  hxtMeshCreate          ( HXTMesh** mesh);
 HXTStatus  hxtMeshDelete          ( HXTMesh** meshPtr);
 
-#ifdef HXT_CORE_FILEIO
+// mesh I/O
 HXTStatus  hxtMeshReadGmsh       ( HXTMesh* mesh, const char* filename);
 HXTStatus  hxtMeshWriteGmsh      ( HXTMesh* mesh, const char* filename);
-#endif
+
 
 #ifdef __cplusplus
 }
diff --git a/contrib/hxt/core/include/hxt_opt.h b/contrib/hxt/core/include/hxt_opt.h
new file mode 100644
index 0000000000000000000000000000000000000000..d7f069e05686c9e75540d7cc786814e46e42265b
--- /dev/null
+++ b/contrib/hxt/core/include/hxt_opt.h
@@ -0,0 +1,179 @@
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
+#ifndef __HXT_OPT_H__
+#define __HXT_OPT_H__
+
+#include "hxt_message.h"
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/****************************************************************************************
+ *  argument type: the type of the argument that must be given to the option
+ * or HXT[_NO]_FLAG to indicate that the option doesn't have an argument
+ ***************************************************************************************/
+typedef enum {
+// flags
+  // no argument must be given, the value must be an integer set to 0 (it is set to 1 when option is called)
+    HXT_FLAG,
+  // no argument must be given, the value must be an integer set to 1 (it is set to 0 when option is called)
+    HXT_NO_FLAG,
+
+// floating point values:
+    HXT_DOUBLE,
+    HXT_FLOAT,
+
+// integer values
+    HXT_INT,
+    HXT_I64,
+    HXT_I32,
+    HXT_I16,
+
+// unsigned integer values
+    HXT_UNSIGNED,
+    HXT_U64,
+    HXT_U32,
+    HXT_U16,
+
+// strings values
+    HXT_STRING,
+    HXT_EXISTING_FILENAME,
+    HXT_NEW_FILENAME,
+    HXT_ASK_TO_ERASE_FILENAME
+} HXTOptionArgumentType;
+
+/*************************************************************************************
+ *  Constraints on the accepted range of the value given in argument                 *
+ ************************************************************************************/
+typedef struct {
+  // acceptable range for floating-point values
+  double doubleMin;
+  double doubleMax;
+
+  // acceptable range for integer values
+  long long int intMin;
+  long long int intMax;
+
+  // acceptable range for unsigned integer values
+  unsigned long long unsignedMin;
+  unsigned long long unsignedMax;
+
+  // required prefix and suffix to the string (NULL pointer are omitted)
+  const char* stringPrefix;
+  const char* stringSuffix;
+
+  // character allowed, required or forbidden (NULL pointer are omitted)
+  const char* stringCharAllowed;
+} HXTOptionArgumentConstraints;
+
+#define HXT_ALPHA_LOWERCASE_CHARACTERS        "abcdefghijklmnopqrstuvwxyz"
+#define HXT_ALPHA_UPPERCASE_CHARACTERS        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+#define HXT_ALPHA_CHARACTERS                  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+#define HXT_NUMERIC_CHARACTERS                "0123456789"
+#define HXT_ALPHANUMERIC_LOWERCASE_CHARACTERS "abcdefghijklmnopqrstuvwxyz0123456789"
+#define HXT_ALPHANUMERIC_UPPERCASE_CHARACTERS "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
+#define HXT_ALPHANUMERIC_CHARACTERS  \
+    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
+#define HXT_PRINTABLE_VISIBLE_CHARACTERS  \
+    "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
+#define HXT_PRINTABLE_CHARACTERS \
+    "\t\n !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
+
+// built-in hxtOptionArg
+extern const HXTOptionArgumentConstraints HXT_POSITIVE_RANGE;
+
+extern const HXTOptionArgumentConstraints HXT_ALPHA_LOWERCASE_RANGE;
+extern const HXTOptionArgumentConstraints HXT_ALPHA_UPPERCASE_RANGE;
+extern const HXTOptionArgumentConstraints HXT_ALPHA_RANGE;
+extern const HXTOptionArgumentConstraints HXT_NUMERIC_RANGE;
+extern const HXTOptionArgumentConstraints HXT_ALPHANUMERIC_LOWERCASE_RANGE;
+extern const HXTOptionArgumentConstraints HXT_ALPHANUMERIC_UPPERCASE_RANGE;
+extern const HXTOptionArgumentConstraints HXT_ALPHANUMERIC_RANGE;
+extern const HXTOptionArgumentConstraints HXT_PRINTABLE_VISIBLE_RANGE;
+extern const HXTOptionArgumentConstraints HXT_PRINTABLE_RANGE;
+
+extern const HXTOptionArgumentConstraints HXT_0_1_RANGE;
+extern const HXTOptionArgumentConstraints HXT_0_2_RANGE;
+extern const HXTOptionArgumentConstraints HXT_0_3_RANGE;
+extern const HXTOptionArgumentConstraints HXT_0_4_RANGE;
+extern const HXTOptionArgumentConstraints HXT_0_5_RANGE;
+extern const HXTOptionArgumentConstraints HXT_0_10_RANGE;
+extern const HXTOptionArgumentConstraints HXT_0_20_RANGE;
+extern const HXTOptionArgumentConstraints HXT_0_50_RANGE;
+extern const HXTOptionArgumentConstraints HXT_0_100_RANGE;
+extern const HXTOptionArgumentConstraints HXT_0_1000_RANGE;
+
+
+HXTStatus hxtAddOption(char short_name,
+                       const char* longName,
+                       const char* description,
+                       HXTOptionArgumentType valueType,
+                       const HXTOptionArgumentConstraints* constraints,
+                       void* valuePtr);
+
+/* Trailing options are options without an option name.
+ * the order in which they are added is important !
+ * by default, the last trailing option is optional
+ * you can add an empty trailing option (a trailing option with valuePtr==NULL) at the end to make the last trailing option required
+ * example:
+ *
+ *    const char* input = NULL;
+ *    HXT_CHECK(hxtAddTrailingOption("INPUT_MESH", HXT_EXISTING_FILENAME, NULL, &input));
+ *
+ *    // without the next line, the user would be allowed not giving an input mesh file in the command line
+ *
+ *    HXT_CHECK(hxtAddTrailingOption(NULL, 0, NULL, NULL));
+ *
+ *    // this empty trailing option option ensure that an input mesh file is required
+*/
+static inline HXTStatus hxtAddTrailingOption(
+                      const char* argumentName, // name to use in the usage line ./program [Options] trailingArg1 trailingArg2 ...
+                      HXTOptionArgumentType valueType,
+                      const HXTOptionArgumentConstraints* constraints,
+                      void* valuePtr)
+{
+  HXT_CHECK( hxtAddOption('\0', NULL, argumentName, valueType, constraints, valuePtr) );
+  return HXT_STATUS_OK;
+}
+
+// use the HXT_PARSE_COMMAND_LINE macro instead
+HXTStatus hxtGetOptionHelp(char message[16384],
+                           const char* programName,
+                           const char* programDescription,
+                           const char* additionalInfo);
+
+// use the HXT_PARSE_COMMAND_LINE macro instead
+HXTStatus hxtParseOptions(const int argc, char* argv[]);
+
+// This macro should be placed in the main, after all options are added !
+#define HXT_PARSE_COMMAND_LINE(argc, argv, programName, programDescription, additionalInfo)   \
+do{                                                                                           \
+  char help[16384];                                                                           \
+  HXTStatus status = hxtGetOptionHelp(help, programName, programDescription, additionalInfo); \
+  if(status==HXT_STATUS_OK)                                                                   \
+    status = hxtParseOptions(argc, argv);                                                     \
+  if(status!=HXT_STATUS_OK && status!=HXT_STATUS_INTERNAL) {                                  \
+    HXT_TRACE(status);                                                                        \
+    puts("\n  ==> Help on Error\n\n                              ---\n");                     \
+  }                                                                                           \
+  if(status!=HXT_STATUS_OK) {                                                                 \
+    printf("%s", help);                                                                       \
+    return status!=HXT_STATUS_INTERNAL?status:0;                                              \
+  }                                                                                           \
+} while(0);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/contrib/hxt/core/include/hxt_tools.h b/contrib/hxt/core/include/hxt_tools.h
index cefd41eda89f2c6c9cdd193f52d42fa0f546fcd6..12fbee85eea3379279eecfc13456b38f0aea49b9 100644
--- a/contrib/hxt/core/include/hxt_tools.h
+++ b/contrib/hxt/core/include/hxt_tools.h
@@ -16,6 +16,10 @@ extern "C" {
 #include "hxt_message.h"
 #include <string.h>
 #include <stdint.h>
+#include <math.h>
+#ifndef M_PI
+  #define M_PI 3.14159265358979323846264338327950
+#endif // !M_PI
 
 /* define SIMD ALIGNMENT */
 #ifndef SIMD_ALIGN
diff --git a/contrib/hxt/core/src/hxt_mesh.c b/contrib/hxt/core/src/hxt_mesh.c
index acc2980767fb3e533340d6609085b867b70b2aa9..bf07c31e9e2458a0eb9c9b5c339597e1d83d2bff 100644
--- a/contrib/hxt/core/src/hxt_mesh.c
+++ b/contrib/hxt/core/src/hxt_mesh.c
@@ -96,13 +96,6 @@ HXTStatus hxtMeshDelete ( HXTMesh** mesh) {
 }
 
 
-
-
-
-
-
-#ifdef HXT_CORE_FILEIO
-
 // TODO: more checking of fgets
 HXTStatus ReadNodesFromGmsh(FILE *fp,  HXTMesh* m){
   rewind (fp);
@@ -583,5 +576,3 @@ HXTStatus  hxtMeshWriteGmsh  ( HXTMesh* mesh , const char *filename) {
   return HXT_STATUS_OK;
 }
 
-#endif
-
diff --git a/contrib/hxt/core/src/hxt_opt.c b/contrib/hxt/core/src/hxt_opt.c
new file mode 100644
index 0000000000000000000000000000000000000000..ba9b7e6c4d7d56832d1ec90479866da455ad4a45
--- /dev/null
+++ b/contrib/hxt/core/src/hxt_opt.c
@@ -0,0 +1,819 @@
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
+#include "hxt_opt.h"
+#include "hxt_tools.h"
+#include <float.h>
+#include <errno.h>
+#include <limits.h>
+
+
+
+const HXTOptionArgumentConstraints HXT_POSITIVE_RANGE = {
+	0, DBL_MAX,
+	0, LLONG_MAX,
+	0, ULLONG_MAX,
+	NULL, NULL, NULL
+};
+const HXTOptionArgumentConstraints HXT_ALPHA_LOWERCASE_RANGE = {
+	-DBL_MAX, DBL_MAX,
+	LLONG_MIN, LLONG_MAX,
+	0, ULLONG_MAX,
+	NULL, NULL, HXT_ALPHA_LOWERCASE_CHARACTERS
+};
+const HXTOptionArgumentConstraints HXT_ALPHA_UPPERCASE_RANGE = {
+	-DBL_MAX, DBL_MAX,
+	LLONG_MIN, LLONG_MAX,
+	0, ULLONG_MAX,
+	NULL, NULL, HXT_ALPHA_UPPERCASE_CHARACTERS
+};
+const HXTOptionArgumentConstraints HXT_ALPHA_RANGE = {
+	-DBL_MAX, DBL_MAX,
+	LLONG_MIN, LLONG_MAX,
+	0, ULLONG_MAX,
+	NULL, NULL, HXT_ALPHA_CHARACTERS
+};
+const HXTOptionArgumentConstraints HXT_NUMERIC_RANGE = {
+	-DBL_MAX, DBL_MAX,
+	LLONG_MIN, LLONG_MAX,
+	0, ULLONG_MAX,
+	NULL, NULL, HXT_NUMERIC_CHARACTERS
+};
+const HXTOptionArgumentConstraints HXT_ALPHANUMERIC_LOWERCASE_RANGE = {
+	-DBL_MAX, DBL_MAX,
+	LLONG_MIN, LLONG_MAX,
+	0, ULLONG_MAX,
+	NULL, NULL, HXT_ALPHANUMERIC_LOWERCASE_CHARACTERS
+};
+const HXTOptionArgumentConstraints HXT_ALPHANUMERIC_UPPERCASE_RANGE = {
+	-DBL_MAX, DBL_MAX,
+	LLONG_MIN, LLONG_MAX,
+	0, ULLONG_MAX,
+	NULL, NULL, HXT_ALPHANUMERIC_UPPERCASE_CHARACTERS
+};
+const HXTOptionArgumentConstraints HXT_ALPHANUMERIC_RANGE = {
+	-DBL_MAX, DBL_MAX,
+	LLONG_MIN, LLONG_MAX,
+	0, ULLONG_MAX,
+	NULL, NULL, HXT_ALPHANUMERIC_CHARACTERS
+};
+const HXTOptionArgumentConstraints HXT_PRINTABLE_VISIBLE_RANGE = {// between space and ~
+	-DBL_MAX, DBL_MAX,
+	LLONG_MIN, LLONG_MAX,
+	0, ULLONG_MAX,
+	NULL, NULL, HXT_PRINTABLE_VISIBLE_CHARACTERS
+};
+const HXTOptionArgumentConstraints HXT_PRINTABLE_RANGE = {
+	-DBL_MAX, DBL_MAX,
+	LLONG_MIN, LLONG_MAX,
+	0, ULLONG_MAX,
+	NULL, NULL, HXT_PRINTABLE_CHARACTERS
+};
+const HXTOptionArgumentConstraints HXT_0_1_RANGE = {
+	0., 1.,
+	0, 1,
+	0, 1,
+	NULL, NULL, NULL
+};
+const HXTOptionArgumentConstraints HXT_0_2_RANGE = {
+	0., 2.,
+	0, 2,
+	0, 2,
+	NULL, NULL, NULL
+};
+const HXTOptionArgumentConstraints HXT_0_3_RANGE = {
+	0., 3.,
+	0, 3,
+	0, 3,
+	NULL, NULL, NULL
+};
+const HXTOptionArgumentConstraints HXT_0_4_RANGE = {
+	0., 4.,
+	0, 4,
+	0, 4,
+	NULL, NULL, NULL
+};
+const HXTOptionArgumentConstraints HXT_0_5_RANGE = {
+	0., 5.,
+	0, 5,
+	0, 5,
+	NULL, NULL, NULL
+};
+const HXTOptionArgumentConstraints HXT_0_10_RANGE = {
+	0., 10.,
+	0, 10,
+	0, 10,
+	NULL, NULL, NULL
+};
+const HXTOptionArgumentConstraints HXT_0_20_RANGE = {
+	0., 20.,
+	0, 20,
+	0, 20,
+	NULL, NULL, NULL
+};
+const HXTOptionArgumentConstraints HXT_0_50_RANGE = {
+	0., 50.,
+	0, 50,
+	0, 50,
+	NULL, NULL, NULL
+};
+const HXTOptionArgumentConstraints HXT_0_100_RANGE = {
+	0., 100.,
+	0, 100,
+	0, 100,
+	NULL, NULL, NULL
+};
+const HXTOptionArgumentConstraints HXT_0_1000_RANGE = {
+	0., 1000.,
+	0, 1000,
+	0, 1000,
+	NULL, NULL, NULL
+};
+
+
+typedef struct HXTOptionStruct {
+  char shortName;
+  const char* longName;
+  const char* description;
+  const HXTOptionArgumentConstraints* constraints;
+  HXTOptionArgumentType valueType;
+  void* valuePtr;
+} HXTOption;
+
+static HXTOption helpOption = {'h', "help", "Display this help message", NULL, HXT_FLAG, NULL};
+static HXTOption* optionList = NULL;
+static int optionListLength = 0;
+static int optionListSize = 0;
+
+
+#define MAX(a,b) (((a)>(b))?(a):(b))
+
+
+static HXTStatus optionListReserve(int n)
+{
+	if(optionList==NULL) {
+		optionListSize = MAX(16,n);
+		HXT_CHECK( hxtMalloc(&optionList, optionListSize*sizeof(HXTOption)) );
+		optionList[0] = helpOption;
+		optionListLength = 1;
+	}
+	else if(optionListLength + n > optionListSize) {
+		optionListSize = MAX(2*optionListSize, optionListLength + n);
+		HXT_CHECK( hxtRealloc(&optionList, optionListSize) );
+	}
+	return HXT_STATUS_OK;
+}
+
+
+HXTStatus hxtAddOption(char shortName,
+                       const char* longName,
+                       const char* description,
+                       HXTOptionArgumentType valueType,
+                       const HXTOptionArgumentConstraints* constraints,
+                       void* valuePtr)
+{
+	HXT_CHECK( optionListReserve(1) );
+
+#ifndef NDEBUG
+	if(valuePtr==NULL && (shortName!='\0' || longName!=NULL || description!=NULL))
+		return HXT_ERROR_MSG(HXT_STATUS_ERROR, "Adding a non-empty option with a NULL value pointer makes no sense");
+	for (int i=0; i<optionListLength; i++) {
+		if(shortName!='\0' && shortName==optionList[i].shortName)
+			return HXT_ERROR_MSG(HXT_STATUS_ERROR, "-%c is already the short name of another option", shortName);
+	}
+	if(longName!=NULL) {
+		if(longName[0]=='\0')
+			return HXT_ERROR_MSG(HXT_STATUS_ERROR, "Cannot use empty string as a long option name. Use NULL pointer if you do not want a long option name.");
+		if(longName[0]=='-')
+			return HXT_ERROR_MSG(HXT_STATUS_ERROR, "long option \"%s\" cannot begin with a '-'", longName);
+		for (int i=0; longName[i]!='\0'; i++) {
+			if(longName[i]<=' ')
+				return HXT_ERROR_MSG(HXT_STATUS_ERROR, "long option \"%s\" should only contain printable characters", longName);
+		}
+		for (int i=0; i<optionListLength; i++) {
+			if(optionList[i].longName!=NULL && strcmp(longName, optionList[i].longName)==0)
+				return HXT_ERROR_MSG(HXT_STATUS_ERROR, "--%s is already the long name of another option", longName);
+		}
+	}
+#endif
+
+	if(shortName=='\0' && (longName==NULL || longName[0]=='\0') &&
+	   (valueType==HXT_FLAG || valueType==HXT_NO_FLAG) && valuePtr!=NULL) {
+		return HXT_ERROR_MSG(HXT_STATUS_ERROR, "A flag must have an option name. Therefore, it can not be a trailing option");
+	}
+
+	optionList[optionListLength].shortName = shortName;
+	optionList[optionListLength].longName = longName;
+	optionList[optionListLength].description = description;
+	optionList[optionListLength].valueType = valueType;
+	optionList[optionListLength].constraints = constraints;
+	optionList[optionListLength].valuePtr = valuePtr;
+	optionListLength++;
+
+	return HXT_STATUS_OK;
+}
+
+
+/*********************************************************************
+*  search a long option inside the list                              *
+*********************************************************************/
+static int searchLongOption(const char* string)
+{
+	for (int i=0; i<optionListLength; i++) {
+		if(optionList[i].longName!=NULL &&
+		   strcmp(optionList[i].longName, string)==0) {
+			return i;
+		}
+	}
+
+	return -1;
+}
+
+
+/*********************************************************************
+*  search a short option inside the list                             *
+*********************************************************************/
+static int searchShortOption(char c)
+{
+	for (int i=0; i<optionListLength; i++) {
+		if(c==optionList[i].shortName) {
+			return i;
+		}
+	}
+	return -1;
+}
+
+
+int fileExists(const char *fname)
+{
+    FILE *file;
+    if ((file = fopen(fname, "r")))
+    {
+        fclose(file);
+        return 1;
+    }
+    return 0;
+}
+
+
+static const char* getArgTypeName(HXTOptionArgumentType t){
+	switch(t) {
+	case HXT_FLAG:
+	case HXT_NO_FLAG:
+		return "(none)";
+    case HXT_DOUBLE:
+    	return "a double";
+    case HXT_FLOAT:
+    	return "a float";
+    case HXT_INT:
+    	return "an integer ";
+    case HXT_I64:
+    	return "a 64-bit integer";
+    case HXT_I32:
+    	return "a 32-bit integer";
+    case HXT_I16:
+    	return "a 16-bit integer";
+    case HXT_UNSIGNED:
+    	return "an unsigned integer ";
+    case HXT_U64:
+    	return "a 64-bit unsigned integer";
+    case HXT_U32:
+    	return "a 32-bit unsigned integer";
+    case HXT_U16:
+    	return "a 16-bit unsigned integer";
+    default:
+		return "a string";
+	}
+}
+
+
+/*********************************************************************
+*  scan the argument and verify its validity                         *
+*********************************************************************/
+static HXTStatus doOption(HXTOption* opt,
+	                      const char* arg,
+	                      const char* optName)
+{
+	if(opt->valueType==HXT_FLAG) {
+		*(int*) opt->valuePtr = 1;
+		return HXT_STATUS_OK;
+	}
+	if(opt->valueType==HXT_NO_FLAG) {
+		*(int*) opt->valuePtr = 0;
+		return HXT_STATUS_OK;
+	}
+
+	char* endptr = NULL;
+	double r = 0;
+	unsigned long long u = 0;
+	long long int i = 0;
+	const char* s = NULL;
+
+	int isDouble = 0, isInteger = 0, isUnsigned = 0;
+
+	if(opt->valueType==HXT_DOUBLE || opt->valueType==HXT_FLOAT) {
+		isDouble = 1;
+		r = strtod(arg, &endptr);
+	}
+	else if(opt->valueType==HXT_INT ||
+	        opt->valueType==HXT_I64 ||
+	        opt->valueType==HXT_I32 ||
+	        opt->valueType==HXT_I16) {
+		isInteger = 1;
+		i = strtoll(arg, &endptr, 10);
+	}
+	else if(opt->valueType==HXT_UNSIGNED ||
+	        opt->valueType==HXT_U64 ||
+	        opt->valueType==HXT_U32 ||
+	        opt->valueType==HXT_U16) {
+		isUnsigned = 1;
+		u = strtoull(arg, &endptr, 10);
+	}
+	else {
+		s = arg;
+	}
+
+	// verify the validity
+	if(errno == ERANGE){
+range_error:
+		return HXT_ERROR_MSG(HXT_STATUS_RANGE_ERROR,
+		       "cannot convert argument \"%s\" of option \"%s\" to %s (range overflow)",
+		       arg, optName, getArgTypeName(opt->valueType));
+	}
+	else if (arg == endptr)
+	{
+		return HXT_ERROR_MSG(HXT_STATUS_FORMAT_ERROR,
+		       "cannot convert argument \"%s\" of option \"%s\" to %s (no digit)",
+		       arg, optName, getArgTypeName(opt->valueType));
+	}
+	else if(endptr!=NULL && *endptr!='\0') {
+		return HXT_ERROR_MSG(HXT_STATUS_FORMAT_ERROR,
+		       "cannot convert argument \"%s\" of option \"%s\" to %s (trailing unvalid characters)",
+		       arg, optName, getArgTypeName(opt->valueType));
+	}
+
+	// verify the conversion is possible
+	switch(opt->valueType) {
+	// floating point values:
+		case HXT_DOUBLE:
+			*(double*) opt->valuePtr = r;
+			break;
+	    case HXT_FLOAT:
+		    if((float)r!=r) goto range_error;
+		    *(float*) opt->valuePtr = r;
+		    break;
+	// integer values
+	    case HXT_INT:
+		    if((int)i!=i) goto range_error;
+		    *(int*) opt->valuePtr = i;
+		    break;
+	    case HXT_I64:
+		    if((int64_t)i!=i) goto range_error;
+		    *(int64_t*) opt->valuePtr = i;
+		    break;
+	    case HXT_I32:
+		    if((int32_t)i!=i) goto range_error;
+		    *(int32_t*) opt->valuePtr = i;
+		    break;
+	    case HXT_I16:
+		    if((int16_t)i!=i) goto range_error;
+		    *(int16_t*) opt->valuePtr = i;
+		    break;
+	// unsigned integer values
+	    case HXT_UNSIGNED:
+		    if((unsigned)u!=u) goto range_error;
+		    *(unsigned*) opt->valuePtr = u;
+		    break;
+	    case HXT_U64:
+		    if((uint64_t)u!=u) goto range_error;
+		    *(uint64_t*) opt->valuePtr = u;
+		    break;
+	    case HXT_U32:
+		    if((uint32_t)u!=u) goto range_error;
+		    *(uint32_t*) opt->valuePtr = u;
+		    break;
+	    case HXT_U16:
+		    if((uint16_t)u!=u) goto range_error;
+		    *(uint16_t*) opt->valuePtr = u;
+		    break;
+   // string values
+		case HXT_EXISTING_FILENAME:
+			if(!fileExists(s))
+				return HXT_ERROR_MSG(HXT_STATUS_FILE_CANNOT_BE_OPENED,
+				                     "file \"%s\" does not exist", s);
+			*(const char**) opt->valuePtr = s;
+			break;
+		case HXT_NEW_FILENAME:
+			if(fileExists(s))
+				return HXT_ERROR_MSG(HXT_STATUS_FILE_CANNOT_BE_OPENED,
+				                     "file \"%s\" already exists", s);
+			*(const char**) opt->valuePtr = s;
+			break;
+		case HXT_ASK_TO_ERASE_FILENAME:
+			if(fileExists(s)) {
+				char memory[64];
+				HXT_INFO("file \"%s\" already exists\n do you want to overwrite it ? y/N", s);
+				char* string = fgets(memory, 64, stdin);
+				if(string==NULL || (string[0]!='y' && string[0]!='Y') )
+					return HXT_ERROR_MSG(HXT_STATUS_FILE_CANNOT_BE_OPENED, "aborting");
+			}
+			/* fall through */
+
+		default:
+			*(const char**) opt->valuePtr = s;
+	    	break;
+	}
+
+	if(opt->constraints==NULL)
+		return HXT_STATUS_OK;
+
+
+	if(isDouble){
+		if(r < opt->constraints->doubleMin || r > opt->constraints->doubleMax)
+			return HXT_ERROR_MSG(HXT_STATUS_RANGE_ERROR,
+			                     "cannot convert argument \"%s\" of option \"%s\" "
+			                     "to %s between %g and %g (range overflow)",
+			                     arg, optName, getArgTypeName(opt->valueType),
+								 opt->constraints->doubleMin, opt->constraints->doubleMax);
+	}
+	else if(isInteger){
+		if(i < opt->constraints->intMin || i > opt->constraints->intMax)
+			return HXT_ERROR_MSG(HXT_STATUS_RANGE_ERROR,
+			                     "cannot convert argument \"%s\" of option \"%s\" "
+			                     "to %s between %lld and %lld (range overflow)",
+			                     arg, optName, getArgTypeName(opt->valueType),
+								 opt->constraints->intMin, opt->constraints->intMax);
+	}
+	else if(isUnsigned){
+		if(u < opt->constraints->unsignedMin || u > opt->constraints->unsignedMax)
+			return HXT_ERROR_MSG(HXT_STATUS_RANGE_ERROR,
+			                     "cannot convert argument \"%s\" of option \"%s\" "
+			                     "to %s between %llu and %llu (range overflow)",
+			                     arg, optName, getArgTypeName(opt->valueType),
+								 opt->constraints->unsignedMin, opt->constraints->unsignedMax);
+	}
+	else {
+		if(opt->constraints->stringPrefix!=NULL) {
+			const char* prefix = opt->constraints->stringPrefix;
+			size_t lenpre = strlen(prefix), lens = strlen(s);
+			if(lens < lenpre || strncmp(prefix, s, lenpre) != 0)
+				return HXT_ERROR_MSG(HXT_STATUS_ERROR, "argument \"%s\" of option \"%s\" is not prefixed by \"%s\"", arg, optName, prefix);
+		}
+		if(opt->constraints->stringSuffix!=NULL) {
+			const char* suffix = opt->constraints->stringSuffix;
+			size_t lensuf = strlen(suffix), lens = strlen(s);
+			if(lens < lensuf || strcmp(suffix, s + lens - lensuf) != 0)
+				return HXT_ERROR_MSG(HXT_STATUS_ERROR, "argument \"%s\" of option \"%s\" is not suffixed by \"%s\"", arg, optName, suffix);
+		}
+		if(opt->constraints->stringCharAllowed!=NULL) {
+			const char* allowed = opt->constraints->stringCharAllowed;
+			for (int j=0; s[j]!='\0'; j++) {
+				int found = 0;
+				int special = 0;
+				if(opt->constraints==&HXT_ALPHA_LOWERCASE_RANGE
+				|| opt->constraints==&HXT_ALPHA_RANGE
+				|| opt->constraints==&HXT_ALPHANUMERIC_LOWERCASE_RANGE
+				|| opt->constraints==&HXT_ALPHANUMERIC_RANGE) {
+					special = 1;
+					if(s[j]>='a' && s[j]<='z') found = 1;
+				}
+				if(opt->constraints==&HXT_ALPHA_UPPERCASE_RANGE
+				|| opt->constraints==&HXT_ALPHA_RANGE
+				|| opt->constraints==&HXT_ALPHANUMERIC_UPPERCASE_RANGE
+				|| opt->constraints==&HXT_ALPHANUMERIC_RANGE) {
+					special = 1;
+					if(s[j]>='A' && s[j]<='Z') found = 1;
+				}
+				if(opt->constraints==&HXT_NUMERIC_RANGE
+				|| opt->constraints==&HXT_ALPHANUMERIC_LOWERCASE_RANGE
+				|| opt->constraints==&HXT_ALPHANUMERIC_UPPERCASE_RANGE
+				|| opt->constraints==&HXT_ALPHANUMERIC_RANGE) {
+					special = 1;
+					if(s[j]>='0' && s[j]<='9') found = 1;
+				}
+				if(opt->constraints==&HXT_PRINTABLE_VISIBLE_RANGE
+				|| opt->constraints==&HXT_PRINTABLE_RANGE) {
+					special = 1;
+					if(s[j]>' ' && s[j]<='~') found = 1;
+				}
+				if(opt->constraints==&HXT_PRINTABLE_RANGE) {
+					special = 1;
+					if(s[j]==' ' || s[j]=='\t' || s[j]=='\n') found = 1;
+				}
+				if(special!=1) {
+					for (int k=0; allowed[k]!='\0'; k++) {
+						if(s[j]==allowed[k]){
+							found = 1;
+							break;
+						}
+					}
+				}
+				
+				if(found==0)
+					return HXT_ERROR_MSG(HXT_STATUS_FORMAT_ERROR, "argument \"%s\" of option \"%s\" contain the unvalid character %c", s[j]);
+			}
+		}
+	}
+
+	return HXT_STATUS_OK;
+}
+
+
+static int getNextTrailingOption(int n) {
+	for (int i=n+1; i<optionListLength; i++) {
+		if(optionList[i].shortName=='\0' && optionList[i].longName==NULL) {
+			return i;
+		}
+	}
+	return -1;
+}
+
+
+HXTStatus hxtParseOptions(const int argc, char* argv[])
+{
+	int dashdash = 0;
+	int trailing = getNextTrailingOption(0);
+	for (int i=1; i<argc; i++) {
+		const char *arg = NULL;
+		HXTOption* opt = NULL;
+
+		if(dashdash || argv[i][0]!='-' || (argv[i][0]=='-' && argv[i][1]=='\0')){
+			if(trailing==-1 || optionList[trailing].valuePtr==NULL)
+				return HXT_ERROR_MSG(HXT_STATUS_FORMAT_ERROR,
+				                     "Additional argument \"%s\" does not correspond to any option",
+				                     argv[i]);
+			else
+				HXT_CHECK( doOption(&optionList[trailing], argv[i], optionList[trailing].description) );
+
+			trailing = getNextTrailingOption(trailing);
+		}
+		else if(argv[i][1]=='-') { /* long opt */
+			if(argv[i][2]=='\0') /* -- terminate argument parsing,
+			everything from now on is a trailing option */ {
+				dashdash = 1;
+				continue;
+			}
+
+			char* equalSign = strchr(argv[i]+2,'=');
+			
+			if(equalSign!=NULL){
+				*equalSign = '\0';
+				arg = equalSign + 1;
+			}
+
+			int num = searchLongOption(argv[i]+2);
+			if(num<0){
+				return HXT_ERROR_MSG(HXT_STATUS_FORMAT_ERROR,
+				       "option \"%s\" not found", argv[i]);
+			}
+			opt = &optionList[num];
+
+			if(equalSign!=NULL){
+				*equalSign = '=';
+				if(opt->valueType==HXT_FLAG || opt->valueType==HXT_NO_FLAG){
+					return HXT_ERROR_MSG(HXT_STATUS_FORMAT_ERROR,
+					       "option \"%s\" takes no argument", argv[i]);
+				}
+			}
+			else{
+				if(num==0) { // it's the help option
+					return HXT_STATUS_INTERNAL;
+				}
+				if(opt->valueType!=HXT_FLAG && opt->valueType!=HXT_NO_FLAG) {
+					if(argc<=i+1) {
+						return HXT_ERROR_MSG(HXT_STATUS_FORMAT_ERROR,
+					       "options \"%s\" requires an argument", argv[i]);
+					}
+					else {
+						arg = argv[i+1];
+						i++;
+					}
+				}
+			}
+
+			HXT_CHECK( doOption(opt, arg, argv[i]) );
+		}
+		else{ /* short option */
+			int cond = argv[i][1];
+			for(int j=1; cond; j++){
+				int num = searchShortOption(argv[i][j]);
+				if(num<0){
+					return HXT_ERROR_MSG(HXT_STATUS_FORMAT_ERROR,
+					       "option \'%c\' in \"%s\" not found", argv[i][j], argv[i]);
+				}
+
+				char optName[] = "- ";
+				optName[1] = argv[i][j];
+				cond = argv[i][j+1];
+
+				if(num==0){
+					return HXT_STATUS_INTERNAL;
+				}
+
+				opt = &optionList[num];
+
+				if(opt->valueType!=HXT_FLAG && opt->valueType!=HXT_NO_FLAG){
+					if(cond){
+						arg = argv[i] + j+1;
+						cond = 0; // stop the loop
+					}
+					else if(argc<=i+1) {
+						return HXT_ERROR_MSG(HXT_STATUS_FORMAT_ERROR,
+						       "options \'%c\' in \"%s\" requires an argument", argv[i][j], argv[i]);
+					}
+					else {
+						arg = argv[i+1];
+						i++;
+					}
+				}
+
+				HXT_CHECK( doOption(opt, arg, optName) );
+			}
+		}
+	}
+
+	if(trailing!=-1) {
+		if(getNextTrailingOption(trailing)!=-1)
+			return HXT_ERROR_MSG(HXT_STATUS_FORMAT_ERROR, "No \"%s\" given", optionList[trailing].description);
+	}
+
+	HXT_CHECK( hxtFree(&optionList) );
+
+	return HXT_STATUS_OK;
+}
+
+
+#define MY_SPRINTF(...) *offset+=snprintf(text+ *offset, 16384- *offset, ## __VA_ARGS__ )
+
+static const char* getHelpValueName(HXTOption* opt) {
+	switch(opt->valueType) {
+    case HXT_DOUBLE:
+    case HXT_FLOAT:
+    return "VAL";
+    case HXT_INT:
+    case HXT_I64:
+    case HXT_I32:
+    case HXT_I16:
+    case HXT_UNSIGNED:
+    case HXT_U64:
+    case HXT_U32:
+    case HXT_U16:
+    return "NUM";
+    case HXT_STRING:
+    return "TEXT";
+    case HXT_EXISTING_FILENAME:
+    case HXT_NEW_FILENAME:
+    case HXT_ASK_TO_ERASE_FILENAME:
+    return "FILENAME";
+    default:
+    return "(none)";
+	}
+}
+
+
+static void printOptionLine(HXTOption* opt, char text[16384], int* offset)
+{
+	const int char_max = 30;
+	int oldOffset = *offset;
+	MY_SPRINTF("  ");
+
+	if(opt->shortName!='\0'){
+		if(opt->longName!=NULL){
+			MY_SPRINTF("-%c, ", opt->shortName);
+		}
+		else{
+			MY_SPRINTF("-%c", opt->shortName);
+		}
+	}
+
+	if(opt->longName!=NULL){
+		if(opt->valueType==HXT_FLAG || opt->valueType==HXT_NO_FLAG)
+			MY_SPRINTF("--%s", opt->longName);
+		else
+			MY_SPRINTF("--%s=%s", opt->longName, getHelpValueName(opt));
+
+		
+	}
+
+	int char_count = *offset - oldOffset;
+	if(char_count<char_max)
+		MY_SPRINTF("%*c", char_max - char_count, ' ');
+	else
+		MY_SPRINTF("\n%*c", char_max, ' ');
+
+	// description
+	{
+		int i,k;
+		for (i=0,k=0; opt->description[i+1]!='\0'; i++, k++) {
+			if(opt->description[i]=='\n'){
+				if(opt->description[i+1]=='\n' || opt->description[i+1]=='\0')
+					MY_SPRINTF("%.*s\n", k, opt->description+i-k);
+				else
+					MY_SPRINTF("%.*s\n%*c", k, opt->description+i-k, char_max+2, ' ');
+				k=-1;
+			}
+		}
+		MY_SPRINTF("%s", opt->description+i-k);
+	}
+
+	// default argument
+	if(opt->valueType!=HXT_FLAG && opt->valueType!=HXT_NO_FLAG)
+	{
+		double r = 0;
+		unsigned long long u = 0;
+		long long int i = 0;
+		MY_SPRINTF("\n%*cdefault: %s=", char_max+1, ' ', getHelpValueName(opt));
+		switch(opt->valueType) {
+	    case HXT_DOUBLE:
+	    MY_SPRINTF("%g", *(double*) opt->valuePtr);
+	    break;
+	    case HXT_FLOAT:
+	    r = *(float*) opt->valuePtr;
+	    MY_SPRINTF("%g", r);
+	    break;
+	    case HXT_INT:
+		MY_SPRINTF("%d", *(int*) opt->valuePtr);
+	    break;
+	    case HXT_I64:
+	    i = *(int64_t*) opt->valuePtr;
+	    MY_SPRINTF("%lld", i);
+	    break;
+	    case HXT_I32:
+	    i = *(int32_t*) opt->valuePtr;
+	    MY_SPRINTF("%lld", i);
+	    break;
+	    case HXT_I16:
+	    i = *(int16_t*) opt->valuePtr;
+	    MY_SPRINTF("%lld", i);
+	    break;
+	    case HXT_UNSIGNED:
+	    MY_SPRINTF("%u", *(unsigned*) opt->valuePtr);
+	    break;
+	    case HXT_U64:
+	    u = *(uint64_t*) opt->valuePtr;
+	    MY_SPRINTF("%llu", u);
+	    break;
+	    case HXT_U32:
+	    u = *(uint32_t*) opt->valuePtr;
+	    MY_SPRINTF("%llu", u);
+	    break;
+	    case HXT_U16:
+	    u = *(uint16_t*) opt->valuePtr;
+	    MY_SPRINTF("%llu", u);
+	    break;
+	    case HXT_STRING:
+	    case HXT_EXISTING_FILENAME:
+	    case HXT_NEW_FILENAME:
+	    case HXT_ASK_TO_ERASE_FILENAME:
+	    if(opt->valuePtr!=NULL)
+	    	MY_SPRINTF("%s", *(const char**) opt->valuePtr);
+	    break;
+	    default:
+	    break;
+		}
+	}
+
+	MY_SPRINTF("\n");
+}
+
+
+HXTStatus hxtGetOptionHelp(char text[16384],
+                           const char* programName,
+                           const char* programDescription,
+                           const char* additionalInfo)
+{
+	int offsetval = 0;
+	int* offset = &offsetval;
+	if(programName!=NULL) {
+		MY_SPRINTF("Usage:  %s [OPTION]...", programName);
+		int n = getNextTrailingOption(0);
+		while(n!=-1 && optionList[n].valuePtr!=NULL) {
+			int n2 = getNextTrailingOption(n);
+			if(optionList[n].shortName=='\0' && optionList[n].longName==NULL && optionList[n].description!=NULL) {
+				if(n2==-1)
+					MY_SPRINTF(" [%s]", optionList[n].description);
+				else
+					MY_SPRINTF(" %s", optionList[n].description);
+			}
+			n=n2;
+		}
+	}
+
+	if(programDescription!=NULL)
+		MY_SPRINTF("\n\n%s", programDescription);
+	MY_SPRINTF("\n\n");
+
+	for (int i=0; i<optionListLength; i++) {
+		if(optionList[i].shortName!='\0' || optionList[i].longName!=NULL)
+			printOptionLine(&optionList[i], text, offset);
+	}
+
+	if(additionalInfo)
+		MY_SPRINTF("%s\n", additionalInfo);
+	return HXT_STATUS_OK;
+}
\ No newline at end of file
diff --git a/contrib/hxt/predicates/CMakeLists.txt b/contrib/hxt/predicates/CMakeLists.txt
index 6b12f414f1708905f194387488f8c815bab2dc01..b53b60341333a66ed2a02f4d4af8f4d0f92fb674 100644
--- a/contrib/hxt/predicates/CMakeLists.txt
+++ b/contrib/hxt/predicates/CMakeLists.txt
@@ -1,32 +1,53 @@
 cmake_minimum_required(VERSION 3.9)
 project(hxt_predicates C)
 
+# include guard for CMake:
+# if you plan to include multiple directory that depend on this one,
+# you need to include this directory first
 if(TARGET hxt_predicates)
-  # header guard for CMake. You need to include this directory first
   return()
 endif()
 
+
+#################################################################################
+# Options (other than inherited ones)
+#################################################################################
+option(HXT_PREDICATES_OBJECT_ONLY "Do not create hxt_predicates library" ON)
+
+
+#################################################################################
+# Library definition
+#################################################################################
 set(HXT_PREDICATES_SRC
-	"${CMAKE_CURRENT_SOURCE_DIR}/src/predicates.c"
-	"${CMAKE_CURRENT_SOURCE_DIR}/include/predicates.h"
-	)
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/predicates.c"
+    "${CMAKE_CURRENT_SOURCE_DIR}/include/predicates.h")
 
-# make an object library (no archive)
-add_library(hxt_predicates OBJECT ${HXT_PREDICATES_SRC})
+if(HXT_PREDICATES_OBJECT_ONLY)
+	# make an object library (no archive)
+	add_library(hxt_predicates OBJECT ${HXT_PREDICATES_SRC})
+else()
+	add_library(hxt_predicates ${HXT_PREDICATES_SRC})
+endif()
 
 target_include_directories(hxt_predicates INTERFACE include)
+target_link_libraries(hxt_predicates m) # link with the math library
+
 
-# do not use extended double precision or arithmetic contraction in predicates.c
+#################################################################################
+# Compilation flags to ensure robustness
+#################################################################################
 if(MSVC OR (CMAKE_C_COMPILER_ID STREQUAL "Intel" AND WIN32))
 	target_compile_options(hxt_predicates PRIVATE "/fp:strict")
 elseif(CMAKE_C_COMPILER_ID STREQUAL "Intel")
-	target_compile_options(${target} ${keyword} "-fp-model" "strict")
+	target_compile_options(hxt_predicates PRIVATE "-fp-model=strict")
 elseif(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang")
-	target_compile_options(hxt_predicates PRIVATE "-fno-unsafe-math-optimizations" "-ffp-contract=off")
+	target_compile_options(hxt_predicates
+	                       PRIVATE
+	                       "-fno-unsafe-math-optimizations" "-ffp-contract=off")
 else()
 	message(WARNING
-		"Unsupported compiler !
-		 Make sure compiled functions from predicates.c
-		 do NOT use extended double precision and follow IEEE754 standard.
-		 It is crucial for the robustness of geometric predicates.")
+	        "Unsupported compiler !
+	         Make sure compiled functions from predicates.c
+	         do NOT use extended double precision and follow IEEE754 standard.
+	         It is crucial for the robustness of geometric predicates.")
 endif()
diff --git a/contrib/hxt/reparam/CMakeLists.txt b/contrib/hxt/reparam/CMakeLists.txt
index 498faf3150952c5297591524a8055c5ee0875c05..caa1e03cca5a83b08a1e41b6fd66465af295d174 100644
--- a/contrib/hxt/reparam/CMakeLists.txt
+++ b/contrib/hxt/reparam/CMakeLists.txt
@@ -1,11 +1,24 @@
 cmake_minimum_required(VERSION 3.9)
 project(hxt_reparam C)
 
-# most options are inherited from hxt_core (see ../core/CMakeList.txt)
+# include guard for CMake:
+# if you plan to include multiple directory that depend on this one,
+# you need to include this directory first
+if(TARGET hxt_reparam)
+  return()
+endif()
+
 
-option(HXT_ENABLE_PETSC "USE PETSc as linear solver  (requires petsc compile without mpi and for real numbers)" ON)
+#################################################################################
+# Options
+#################################################################################
+option(HXT_ENABLE_PETSC "USE PETSc as linear solver (requires petsc compile without mpi and for real numbers)" ON)
 option(HXT_REPARAM_OBJECT_ONLY "Do not create hxt_reparam library" OFF)
 
+
+#################################################################################
+# Library definition
+#################################################################################
 set(HXT_REPARAM_SRC
     "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_edge.c"
     "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_curvature.c"
@@ -21,26 +34,25 @@ set(HXT_REPARAM_SRC
     "${CMAKE_CURRENT_SOURCE_DIR}/include/hxt_curvature.h"
     "${CMAKE_CURRENT_SOURCE_DIR}/include/hxt_edge.h"
     "${CMAKE_CURRENT_SOURCE_DIR}/include/hxt_linear_system.h"
-    "${CMAKE_CURRENT_SOURCE_DIR}/include/hxt_mean_values.h"
-   )
+    "${CMAKE_CURRENT_SOURCE_DIR}/include/hxt_mean_values.h")
 
 if(HXT_REPARAM_OBJECT_ONLY)
-  add_library(hxt_reparam OBJECT ${HXT_REPARAM_SRC})
+	add_library(hxt_reparam OBJECT ${HXT_REPARAM_SRC})
 else()
-  add_library(hxt_reparam ${HXT_REPARAM_SRC})
+	add_library(hxt_reparam ${HXT_REPARAM_SRC})
 endif()
 
 add_subdirectory(../core "${CMAKE_CURRENT_BINARY_DIR}/core")
 
-target_link_libraries(hxt_reparam PUBLIC hxt_core)
+target_link_libraries(hxt_reparam PUBLIC hxt_core PRIVATE m)
 target_compile_features(hxt_reparam PRIVATE c_std_99)
 target_include_directories(hxt_reparam PUBLIC include)
 
 if(ENABLE_PETSC)
-  list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
-  find_package(PETSc REQUIRED)
-  target_include_directories(hxt_reparam PRIVATE "${PETSC_INC}")
-  target_link_libraries(hxt_reparam PRIVATE "${PETSC_LIBS}")
-  target_compile_definitions(hxt_reparam PRIVATE HXT_HAVE_PETSC)
+	list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
+	find_package(PETSc REQUIRED)
+	target_include_directories(hxt_reparam PRIVATE "${PETSC_INC}")
+	target_link_libraries(hxt_reparam PRIVATE "${PETSC_LIBS}")
+	target_compile_definitions(hxt_reparam PRIVATE HXT_HAVE_PETSC)
 endif()
 
diff --git a/contrib/hxt/reparam/include/hxt_edge.h b/contrib/hxt/reparam/include/hxt_edge.h
index 8857d9b0c4cb799444f59f4118ba1875586fa419..4334bc99d89b14031b6fa1b4457d7a0e0a2ec1f9 100644
--- a/contrib/hxt/reparam/include/hxt_edge.h
+++ b/contrib/hxt/reparam/include/hxt_edge.h
@@ -44,6 +44,7 @@ HXTStatus hxtEdgesSetBoundaries(HXTEdges *edges, HXTBoundaries **boundaries);
 
 
 HXTStatus hxtEdgesCreate(HXTMesh *mesh, HXTEdges** edges);
+HXTStatus hxtEdgesCreateNonManifold(HXTMesh *mesh, HXTEdges** edges);
 HXTStatus hxtEdgesDelete(HXTEdges **edges);
 
 int hxtEdgesIsBoundary (HXTEdges *edges, uint32_t *e);
diff --git a/contrib/hxt/reparam/src/hxt_curvature.c b/contrib/hxt/reparam/src/hxt_curvature.c
index 84236357b536fccbce4ea8b272388f36c21755c4..550797ccbeede37f45dde2e9e0996f21ae1ce69c 100644
--- a/contrib/hxt/reparam/src/hxt_curvature.c
+++ b/contrib/hxt/reparam/src/hxt_curvature.c
@@ -1,6 +1,5 @@
 #include "hxt_curvature.h"
 #include "hxt_tools.h"
-#include <math.h>
 #include <stdio.h>
 
 // #include <time.h> // for commented timings
diff --git a/contrib/hxt/reparam/src/hxt_edge.c b/contrib/hxt/reparam/src/hxt_edge.c
index 99538a974a827edc1a51f67eba0ddda6ed12a029..70cc9c6c926499ea1e53e8e6591461fce52932d3 100644
--- a/contrib/hxt/reparam/src/hxt_edge.c
+++ b/contrib/hxt/reparam/src/hxt_edge.c
@@ -1,7 +1,5 @@
 #include "hxt_edge.h"
 #include "hxt_tools.h"
-#include <string.h>
-#include <math.h>
 
 struct hxtLineLoopStruct{
   double length;
@@ -23,6 +21,7 @@ double hxtEdgesLength(const HXTEdges *edges,uint32_t ie){
   
   int i1 = edges->node[2*ie+0];
   int i2 = edges->node[2*ie+1];;
+
   double *x1 = mesh->vertices.coord+i1*4;
   double *x2 = mesh->vertices.coord+i2*4;
   double dx = x1[0]-x2[0];
@@ -357,10 +356,131 @@ HXTStatus hxtEdgesCreate(HXTMesh *mesh, HXTEdges** edges)
   for(uint64_t i=0; i<nTriangles; i++){
     for(uint64_t j=0; j<3; j++){
       uint32_t e = tri2edg[i*3+j];
+      if(edg2tri[e*2+0] == (uint64_t)-1)
+        edg2tri[e*2+0] = i;
+      else
+	if(edg2tri[e*2+1] == (uint64_t)-1)
+	  edg2tri[e*2+1] = i;
+	else
+	  return HXT_ERROR_MSG( HXT_STATUS_ASSERTION_FAILED,"hxt_edge.c:\t topology is wrong for edge creation \n\t At least three triangles (%lu;%lu,%lu) share the same edge\n",i,edg2tri[e*2+0],edg2tri[e*2+1]);
+
+    }
+  }
+  (*edges)->edg2tri = edg2tri;
+  
+  // compute the total number of boundary edges
+  int edgesBdryTotal = 0;
+  for(uint32_t i=0; i<(*edges)->numEdges; i++)
+    if((*edges)->edg2tri[2*i+1] == (uint64_t)-1 ||
+       hxtEdgesIsBoundary ((*edges), &((*edges)->node[2*i]) ))
+      edgesBdryTotal++;      
+  (*edges)->edgesBdryTotal = edgesBdryTotal;
+
+  return HXT_STATUS_OK;
+
+}
+
+
+HXTStatus hxtEdgesCreateNonManifold(HXTMesh *mesh, HXTEdges** edges)
+{
+
+  uint64_t nTriangles  = mesh->triangles.num;
+
+  HXT_CHECK( hxtMalloc (edges,sizeof(HXTEdges)) );
+
+  // build edges of the boundary simply by copying the edges of the
+  // mesh. We prefer to copy because they are sorted
+  uint64_t nEdgesBdry = mesh->lines.num;
+  uint32_t *bdryedges;
+  HXT_CHECK(hxtMalloc(&bdryedges,2*(nEdgesBdry+1)*sizeof(uint32_t))); // allocate at least one :-)
+  (*edges)->bdryedges = bdryedges;
+  memcpy ( bdryedges, mesh->lines.node, 2*nEdgesBdry*sizeof(uint32_t));
+  qsort(bdryedges,nEdgesBdry,2*sizeof(uint32_t),halfedgecmp);
+  (*edges)->nEdgesBdry = nEdgesBdry;
+
+  (*edges)->numEdges = 0;
+  (*edges)->global    = NULL;
+  (*edges)->node      = NULL;
+  (*edges)->color     = NULL;
+  (*edges)->edg2tri   = NULL;
+  (*edges)->tri2edg   = NULL;
+  
+  (*edges)->edg2mesh = mesh;
+ 
+   
+  // build edge
+  uint32_t *halfedges;
+  HXT_CHECK(hxtMalloc(&halfedges,3*3*nTriangles*sizeof(uint32_t)));
+  for(uint64_t i = 0; i<nTriangles; i++) {
+    for(int j=0; j<3; j++){
+      halfedges[i*9+j*3+0] = mesh->triangles.node[3*i+j];//first node of an edge
+      halfedges[i*9+j*3+1] = mesh->triangles.node[3*i+(j+1)%3];//second node of an edge
+      halfedges[i*9+j*3+2] = (uint32_t) i;//triangle having this edge
+    }
+  }
+  qsort(halfedges,nTriangles*3,3*sizeof(uint32_t),halfedgecmp);
+  uint32_t *tri2edg;
+  HXT_CHECK(hxtMalloc(&tri2edg,3*nTriangles*sizeof(uint32_t)));
+  uint32_t nEdges = 0;
+  for(uint64_t i=0; i< nTriangles*3; i++){
+    uint32_t *he = halfedges+i*3;
+    for(int k=0; k<3; k++)
+      if (mesh->triangles.node[he[2]*3+k] == he[0])
+        tri2edg[he[2]*3+k] = nEdges;   
+    if (i+1 == nTriangles*3 || halfedgecmp(he,he+3) != 0)
+      nEdges++;
+  }
+  (*edges)->numEdges = nEdges;
+  (*edges)->tri2edg   = tri2edg;
+
+  
+  uint32_t *node;
+  HXT_CHECK(hxtMalloc(&node,2*nEdges*sizeof(uint32_t)));
+  int p=0;
+  for(uint64_t i=0; i<nTriangles*3; i++){
+    uint32_t *he = halfedges+i*3;
+    if(i+1 == nTriangles*3 || halfedgecmp(he,he+3) != 0){
+      node[p*2+0] = he[0];
+      node[p*2+1] = he[1];
+      p++;
+    }
+  }
+  (*edges)->node = node;
+  HXT_CHECK(hxtFree(&halfedges));
+  uint64_t *edg2tri;
+  HXT_CHECK(hxtMalloc(&edg2tri,2*nEdges*sizeof(uint64_t)));
+  for(uint32_t i=0; i<nEdges*2; i++)
+    edg2tri[i] = -1;
+
+  for(uint64_t i=0; i<nTriangles; i++){
+    for(uint64_t j=0; j<3; j++){
+      uint32_t e = tri2edg[i*3+j];
+
       if(edg2tri[e*2+0] == (uint64_t)-1)
         edg2tri[e*2+0] = i;
       else
         edg2tri[e*2+1] = i;
+
+        // ATTENTION TODO non manifold case fix 
+        
+        /*if(edg2tri[e*2+1] == (uint64_t)-1)*/
+          /*edg2tri[e*2+1] = i;*/
+        /*else{*/
+          /*printf("%lu %lu %lu \n",i+mesh->points.num+mesh->lines.num+1,*/
+                            /*edg2tri[e*2+0]+mesh->points.num+mesh->lines.num+1,*/
+                            /*edg2tri[e*2+1]+mesh->points.num+mesh->lines.num+1);*/
+          /*printf("%d %d %d \n", mesh->triangles.colors[i],*/
+                                /*mesh->triangles.colors[edg2tri[e*2+0]],*/
+                                /*mesh->triangles.colors[edg2tri[e*2+1]]);*/
+          /*uint64_t t1 = edg2tri[2*e+0];*/
+          /*uint64_t t2 = edg2tri[2*e+1];*/
+          /*printf("%d %d %d %d \n", tri2edg[3*i +0], tri2edg[3*i +1], tri2edg[3*i +2], mesh->triangles.colors[i]);*/
+          /*printf("%d %d %d %d \n", tri2edg[3*t1+0], tri2edg[3*t1+1], tri2edg[3*t1+2], mesh->triangles.colors[t1]);*/
+          /*printf("%d %d %d %d \n", tri2edg[3*t2+0], tri2edg[3*t2+1], tri2edg[3*t2+2], mesh->triangles.colors[t2]);*/
+          /*return HXT_ERROR_MSG( HXT_STATUS_ASSERTION_FAILED,*/
+              /*"hxt_edge.c:\t topology is wrong for edge creation \n\t At least three triangles (%lu,%lu,%lu) share the same edge\n",i,edg2tri[e*2+0],edg2tri[e*2+1]);*/
+        /*}*/
+      
     }
   }
   (*edges)->edg2tri = edg2tri;
diff --git a/contrib/hxt/reparam/src/hxt_linear_system_lu.c b/contrib/hxt/reparam/src/hxt_linear_system_lu.c
index 7e530e0c654eaa9910ed53ea5fabecf0e5d2e00a..a8186defc1043383ad61101f762005c62dce9c79 100644
--- a/contrib/hxt/reparam/src/hxt_linear_system_lu.c
+++ b/contrib/hxt/reparam/src/hxt_linear_system_lu.c
@@ -1,7 +1,3 @@
-#include <math.h>
-#include <stdlib.h>
-#include <stdio.h>
-
 #include "hxt_tools.h"
 #include "hxt_linear_system_lu.h"
 
diff --git a/contrib/hxt/reparam/src/hxt_mean_values.c b/contrib/hxt/reparam/src/hxt_mean_values.c
index bc7a24fee46d557031709c2a080fdc65930b281c..582da898d39b73a359c06ff88b621f529b99e12d 100644
--- a/contrib/hxt/reparam/src/hxt_mean_values.c
+++ b/contrib/hxt/reparam/src/hxt_mean_values.c
@@ -4,13 +4,6 @@
 #include "hxt_tools.h"
 
 
-#include <math.h>
-#ifndef M_PI
-  #define M_PI 3.14159265358979323846264338327950
-#endif // !M_PI
-
-
-
 struct HXTMeanValuesStruct{
   HXTEdges *initialEdges;
   double *uv;// parametrization coordinates
diff --git a/contrib/hxt/reparam/src/hxt_non_linear_solver.c b/contrib/hxt/reparam/src/hxt_non_linear_solver.c
index ac15117d3f7c3eb5a24e9b5e054a65f5a003dcc2..14331de74c3b58f2920ce62ae9bddf556bced05f 100644
--- a/contrib/hxt/reparam/src/hxt_non_linear_solver.c
+++ b/contrib/hxt/reparam/src/hxt_non_linear_solver.c
@@ -1,6 +1,5 @@
 #include "hxt_non_linear_solver.h"
 #include "hxt_tools.h"
-#include <math.h>
 
 HXTStatus hxtNewtonRaphson(HXTLinearSystem *nrSys, double *solution, int size, int maxiter, double tol, HXTNonLinearSolverCallbackF *fcb, HXTNonLinearSolverCallbackDF *dfcb, void *data) {
   double *delta, *rhs;
diff --git a/contrib/hxt/tetBR/CMakeLists.txt b/contrib/hxt/tetBR/CMakeLists.txt
index c7feef927c1484c374997d5cddca04bb13900b55..8dcf06c806be3fdb6941143624a190c9204dea2f 100644
--- a/contrib/hxt/tetBR/CMakeLists.txt
+++ b/contrib/hxt/tetBR/CMakeLists.txt
@@ -1,14 +1,26 @@
 cmake_minimum_required(VERSION 3.9)
 project(hxt_tetBR CXX)
 
-# options are inherited from hxt_core (see ../core/CMakeList.txt)
+# include guard for CMake:
+# if you plan to include multiple directory that depend on this one,
+# you need to include this directory first
+if(TARGET hxt_tetBR)
+  return()
+endif()
+
 
+#################################################################################
+# Options
+#################################################################################
 option(HXT_TETBR_OBJECT_ONLY "Do not create hxt_tetBR library" OFF)
 
+
+#################################################################################
+# Library definition
+#################################################################################
 set(HXT_TETBR_SRC
-	"${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_boundary_recovery.cxx"
-	"${CMAKE_CURRENT_SOURCE_DIR}/include/hxt_boundary_recovery.h"
-	)
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_boundary_recovery.cxx"
+    "${CMAKE_CURRENT_SOURCE_DIR}/include/hxt_boundary_recovery.h")
 
 if(HXT_TETBR_OBJECT_ONLY)
 	add_library(hxt_tetBR OBJECT ${HXT_TETBR_SRC})
@@ -23,6 +35,12 @@ target_include_directories(hxt_tetBR
                            PUBLIC include
                            PRIVATE src)
 target_link_libraries(hxt_tetBR
-	                  PUBLIC hxt_core
-                      PRIVATE hxt_predicates)
+                      PUBLIC hxt_core
+                      PRIVATE hxt_predicates m)
 
+if(HXT_ENABLE_OPENMP)
+  find_package(OpenMP 4)
+  if(OpenMP_CXX_FOUND)
+      target_link_libraries(hxt_tetBR PUBLIC OpenMP::OpenMP_CXX)
+  endif()
+endif()
\ No newline at end of file
diff --git a/contrib/hxt/tetBR/src/hxt_boundary_recovery.cxx b/contrib/hxt/tetBR/src/hxt_boundary_recovery.cxx
index 808634e06ebaf97df6aa1cf182d45a4ec6893793..1d34160a87921cdfe1eeb230d733f1f91cae0d58 100644
--- a/contrib/hxt/tetBR/src/hxt_boundary_recovery.cxx
+++ b/contrib/hxt/tetBR/src/hxt_boundary_recovery.cxx
@@ -6,7 +6,6 @@ extern "C" {
 }
 
 #include <assert.h>
-#include <math.h>
 #include <set>
 #include <vector>
 #include <time.h>
diff --git a/contrib/hxt/tetMesh/CMakeLists.txt b/contrib/hxt/tetMesh/CMakeLists.txt
index b44b63b5cfcf43416271001f318f7526bad27d4e..29bc5b077e89bfc268c661d0b3d8c46b12c6f56c 100644
--- a/contrib/hxt/tetMesh/CMakeLists.txt
+++ b/contrib/hxt/tetMesh/CMakeLists.txt
@@ -1,9 +1,24 @@
 cmake_minimum_required(VERSION 3.9)
-project(hxt_tetMesh C)
+project(hxt_tetMesh C CXX)
 
-# most options are inherited from hxt_core (see ../core/CMakeList.txt)
+# include guard for CMake:
+# if you plan to include multiple directory that depend on this one,
+# you need to include this directory first
+if(TARGET hxt_tetMesh)
+  return()
+endif()
+
+
+#################################################################################
+# Options
+#################################################################################
 option(HXT_TETMESH_OBJECT_ONLY "Do not create hxt_tetMesh library" OFF)
+option(HXT_TETMESH_BUILD_CLI "build hxt_tetMesh CLI tools" ON)
 
+
+#################################################################################
+# Library definition
+#################################################################################
 set(HXT_TETMESH_SRC
     "${CMAKE_CURRENT_SOURCE_DIR}/src/HXTSPR.c"
     "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_tetFlag.c"
@@ -21,22 +36,22 @@ set(HXT_TETMESH_SRC
     "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_tetDelaunay.c"
     "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_tetNodalSize.c"
     "${CMAKE_CURRENT_SOURCE_DIR}/src/HXTSPR.h"
-    "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_tetFlag.h"
-    "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_tetOpti.h"
     "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_tetSync.h"
     "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_tetColor.h"
     "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_tetUtils.h"
-    "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_vertices.h"
     "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_smoothing.h"
     "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_tetRefine.h"
-    "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_tetRepair.h"
     "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_tetQuality.h"
     "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_edgeRemoval.h"
-    "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_tetDelaunay.h"
     "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_tetNodalSize.h"
     "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_tetOptiUtils.h"
     "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_tetPartition.h"
+    "${CMAKE_CURRENT_SOURCE_DIR}/include/hxt_tetDelaunay.h"
+    "${CMAKE_CURRENT_SOURCE_DIR}/include/hxt_tetFlag.h"
     "${CMAKE_CURRENT_SOURCE_DIR}/include/hxt_tetMesh.h"
+    "${CMAKE_CURRENT_SOURCE_DIR}/include/hxt_tetOpti.h"
+    "${CMAKE_CURRENT_SOURCE_DIR}/include/hxt_tetRepair.h"
+    "${CMAKE_CURRENT_SOURCE_DIR}/include/hxt_vertices.h"
    )
 
 if(HXT_TETMESH_OBJECT_ONLY)
@@ -53,6 +68,27 @@ target_include_directories(hxt_tetMesh
                            PRIVATE src)
 target_link_libraries(hxt_tetMesh
                       PUBLIC hxt_core
-                      PRIVATE hxt_predicates)
+                      PRIVATE hxt_predicates m)
 target_compile_features(hxt_tetMesh PRIVATE c_std_99)
 
+
+
+#################################################################################
+# Executable definition
+#################################################################################
+if(HXT_TETMESH_BUILD_CLI)
+    # tetMesh_CLI
+    add_executable(tetMesh_CLI "${CMAKE_CURRENT_SOURCE_DIR}/exe/tetMesh_CLI.c")
+
+    add_subdirectory(../tetBR "${CMAKE_CURRENT_BINARY_DIR}/tetBR")
+
+    target_link_libraries(tetMesh_CLI hxt_core hxt_predicates hxt_tetMesh hxt_tetBR)
+
+    # # Delaunay_CLI
+    add_executable(Delaunay_CLI "${CMAKE_CURRENT_SOURCE_DIR}/exe/Delaunay_CLI.c")
+    target_link_libraries(Delaunay_CLI hxt_core hxt_predicates hxt_tetMesh)
+
+    # tetOpti_CLI
+    add_executable(tetOpti_CLI "${CMAKE_CURRENT_SOURCE_DIR}/exe/tetOpti_CLI.c")
+    target_link_libraries(tetOpti_CLI hxt_core hxt_predicates hxt_tetMesh)
+endif()
\ No newline at end of file
diff --git a/contrib/hxt/tetMesh/exe/Delaunay_CLI.c b/contrib/hxt/tetMesh/exe/Delaunay_CLI.c
new file mode 100644
index 0000000000000000000000000000000000000000..61a316299eed2eac30e86b65194922fb458f31fb
--- /dev/null
+++ b/contrib/hxt/tetMesh/exe/Delaunay_CLI.c
@@ -0,0 +1,214 @@
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
+#include "hxt_tetDelaunay.h"
+#include "hxt_opt.h"
+#include "hxt_omp.h"
+
+
+int main(int argc, char** argv) {
+
+  const char* input = NULL;
+  const char* output = NULL;
+  int nthreads = 0;
+  int reproducible = 0;
+  int verbosity = 1;
+  int stat = 0;
+  int preserve_order = 0;
+  uint32_t nvert = 0;
+
+
+  HXT_CHECK( hxtAddOption('i', "input", "Input file in the MSH ASCII file format", HXT_EXISTING_FILENAME, NULL, &input));
+  HXT_CHECK( hxtAddOption('G', "generate",
+                          "Generate N random points following a uniform\n"
+                          "distribution inside the unit cube.\n"
+                          "This option is ignored if an input file is given", HXT_U32, NULL, &nvert) );
+  HXT_CHECK( hxtAddOption('t', "threads",
+                          "Number of threads to use.\n"
+                          " * NUM=0 use OMP_NUM_THREADS\n"
+                          " * NUM<0 use OMP_NUM_PROCS", HXT_INT, NULL, &nthreads) );
+  HXT_CHECK( hxtAddOption('r', "reproducible",
+                          "Delaunay will always produce the same tetrahedra\n"
+                          "given the same points in the same order.\n"
+                          "However, the order in which tetrahedra end up\n"
+                          "can differ when using multiple threads.\n"
+                          "This option re-order tetrahedra to obtain\n"
+                          "a reproducible ouput mesh", HXT_FLAG, NULL, &reproducible) );
+  HXT_CHECK( hxtAddOption('v', "verbosity",
+                          "Verbosity level of output messages\n"
+                          " * NUM=0            : print no information\n"
+                          " * NUM=1            : print some information\n"
+                          " * NUM=2 or ommited : print all information", HXT_INT, &HXT_0_2_RANGE, &verbosity));
+  HXT_CHECK( hxtAddOption('s', "stat",
+                          "Print timing for each portion of the program", HXT_FLAG, NULL, &stat) );
+  HXT_CHECK( hxtAddOption('p', "preserve-pts-order",
+                          "Do not optimize points ordering\n"
+                          "The initial ordering of points is preserved\nbut the program is slower", HXT_FLAG, NULL, &preserve_order) );
+
+  HXT_CHECK( hxtAddTrailingOption("OUTPUT_FILE", HXT_STRING, NULL, &output));
+
+  HXT_PARSE_COMMAND_LINE(argc, argv,
+                         "hxtDelaunay",
+                         "Compute the Delaunay of a set of points. The tetrahedral mesh OUTPUT_FILE is written in the MSH ASCII format",
+                         "Example:\n\thxtDelaunay -st4 input.msh output.msh\n--\nContact: celestin.marot@uclouvain.be");
+
+  if(input==NULL && nvert<=0){
+    return HXT_ERROR_MSG(HXT_STATUS_ERROR ,"No point to triangulate (use -h or --help for help message)");
+  }
+
+  /*******************************************************************************
+   * All options were verified, we can do the Delaunay now...
+   ******************************************************************************/
+
+  double t0=0,t1=0,t2=0,t3=0;
+
+  if(stat)
+    t0 = omp_get_wtime();
+
+  HXTMesh *mesh;
+  HXT_CHECK(hxtMeshCreate(&mesh));
+
+  if(input!=NULL) {
+    HXT_INFO_COND(verbosity>0, "Reading \"%s\"", input);
+    HXT_CHECK(hxtMeshReadGmsh(mesh, input) );
+
+    if(mesh->tetrahedra.num!=0){
+      HXT_WARNING("Mesh file \"%s\" already contains volumes. We delete them",input);
+
+      //tetrahedra
+      HXT_CHECK( hxtAlignedFree(&mesh->tetrahedra.colors) );
+      HXT_CHECK( hxtAlignedFree(&mesh->tetrahedra.node) );
+      mesh->tetrahedra.num = 0;
+      mesh->tetrahedra.size = 0;
+
+      // hexahedra
+      HXT_CHECK( hxtAlignedFree(&mesh->hexahedra.colors) );
+      HXT_CHECK( hxtAlignedFree(&mesh->hexahedra.flag) );
+      HXT_CHECK( hxtAlignedFree(&mesh->hexahedra.node) );
+      HXT_CHECK( hxtAlignedFree(&mesh->hexahedra.neigh) );
+      HXT_CHECK( hxtAlignedFree(&mesh->hexahedra.neighType) );
+      mesh->hexahedra.num = 0;
+      mesh->hexahedra.size = 0;
+
+      // prisms
+      HXT_CHECK( hxtAlignedFree(&mesh->prisms.colors) );
+      HXT_CHECK( hxtAlignedFree(&mesh->prisms.flag) );
+      HXT_CHECK( hxtAlignedFree(&mesh->prisms.node) );
+      HXT_CHECK( hxtAlignedFree(&mesh->prisms.neigh) );
+      HXT_CHECK( hxtAlignedFree(&mesh->prisms.neighType) );
+      mesh->prisms.num = 0;
+      mesh->prisms.size = 0;
+
+      // pyramids
+      HXT_CHECK( hxtAlignedFree(&mesh->pyramids.colors) );
+      HXT_CHECK( hxtAlignedFree(&mesh->pyramids.flag) );
+      HXT_CHECK( hxtAlignedFree(&mesh->pyramids.node) );
+      HXT_CHECK( hxtAlignedFree(&mesh->pyramids.neigh) );
+      HXT_CHECK( hxtAlignedFree(&mesh->pyramids.neighType) );
+      mesh->pyramids.num = 0;
+      mesh->pyramids.size = 0;
+
+      // quads
+      HXT_CHECK( hxtAlignedFree(&mesh->quads.node) );
+      HXT_CHECK( hxtAlignedFree(&mesh->quads.colors) );
+      mesh->quads.num = 0;
+      mesh->quads.num = 0;
+
+    }
+    if((mesh->lines.num!=0 || mesh->triangles.num!=0) && !preserve_order) {
+      HXT_WARNING("Mesh file \"%s\" contains triangles and/or lines.\n"
+                  "\tWe delete them unless the -p/--preserve-pts-order option is specified", input);
+      // triangles
+      HXT_CHECK( hxtAlignedFree(&mesh->triangles.node) );
+      HXT_CHECK( hxtAlignedFree(&mesh->triangles.colors) );
+      mesh->triangles.num = 0;
+      mesh->triangles.size = 0;
+
+      // lines
+      HXT_CHECK( hxtAlignedFree(&mesh->lines.node) );
+      HXT_CHECK( hxtAlignedFree(&mesh->lines.colors) );
+      mesh->lines.num = 0;
+      mesh->lines.size = 0;
+    }
+  }
+  else {
+    HXT_INFO_COND(verbosity>0, "Creating %d random vertices", nvert);
+    HXT_CHECK( hxtAlignedMalloc(&mesh->vertices.coord, nvert*4*sizeof(double)) );
+
+    for (uint32_t i=0; i<nvert; i++) {
+      for (int j=0; j<3; j++) {
+        mesh->vertices.coord[4*i+j] = (double) rand()/RAND_MAX;
+      }
+    }
+
+    mesh->vertices.num = nvert;
+    mesh->vertices.size = nvert;
+  }
+
+  if(stat)
+      t1 = omp_get_wtime();
+
+  HXTDelaunayOptions delOptions = {
+    .bbox = NULL,
+    .nodalSizes = NULL,
+    .numVerticesInMesh = 0,
+    .partitionability = 0,
+    .verbosity = verbosity,
+    .reproducible = reproducible,
+    .delaunayThreads = nthreads
+  };
+
+  if(preserve_order) {
+    hxtNodeInfo* nodeInfo;
+    HXT_CHECK( hxtAlignedMalloc(&nodeInfo, sizeof(hxtNodeInfo)*mesh->vertices.num) );
+
+    #pragma omp parallel for simd aligned(nodeInfo:SIMD_ALIGN)
+    for (uint32_t i=0; i<mesh->vertices.num; i++) {
+      nodeInfo[i].node = i;
+      nodeInfo[i].status = HXT_STATUS_TRYAGAIN;
+    }
+    HXT_CHECK( hxtDelaunaySteadyVertices(mesh, &delOptions, nodeInfo, mesh->vertices.num) );
+    HXT_CHECK( hxtAlignedFree(&nodeInfo) );
+  }
+  else
+    HXT_CHECK( hxtDelaunay(mesh, &delOptions) );
+
+  if(stat)
+      t2 = omp_get_wtime();
+
+  if(output!=NULL){
+    HXT_INFO_COND(verbosity>0, "Writing result to \"%s\"", output);
+    #pragma omp parallel for
+    for (uint64_t i=0; i<mesh->tetrahedra.num; i++) {
+      mesh->tetrahedra.colors[i] = 0;
+    }
+    HXT_CHECK( hxtMeshWriteGmsh(mesh, output) );
+  }
+
+  if(stat){
+    t3 = omp_get_wtime();
+    HXT_INFO("\n\t========== Statistics ==========");
+    HXT_INFO("Mesh contains %" HXTu64 " tetrahedra and %u vertices",
+             mesh->tetrahedra.num,
+             mesh->vertices.num);
+    if(input)
+      HXT_INFO("Reading file \"%s\" took %.2f seconds", input, t1-t0);
+    else
+      HXT_INFO("Creating random points took %.2f seconds", t1-t0);
+    HXT_INFO("Init + BRIO + Delaunay took %.2f seconds (%.2f Mtet/s)", t2-t1, 0.000001*mesh->tetrahedra.num/(t2-t1));
+    if(output)
+      HXT_INFO("Writing file \"%s\" took %.2f seconds",output, t3-t2);
+  }
+
+
+  putchar('\n');
+
+  HXT_CHECK( hxtMeshDelete(&mesh) );
+
+  return 0;
+}
\ No newline at end of file
diff --git a/contrib/hxt/tetMesh/exe/tetMesh_CLI.c b/contrib/hxt/tetMesh/exe/tetMesh_CLI.c
new file mode 100644
index 0000000000000000000000000000000000000000..088197b9a2289b8d7109af2792a9833aba1cecf4
--- /dev/null
+++ b/contrib/hxt/tetMesh/exe/tetMesh_CLI.c
@@ -0,0 +1,119 @@
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
+#include "hxt_tetMesh.h"
+#include "hxt_boundary_recovery.h"
+#include "hxt_opt.h"
+#include "hxt_tools.h"
+#include "hxt_omp.h"
+
+
+static HXTStatus recoveryFun(HXTMesh* mesh, void* userData) {
+  HXT_UNUSED(userData);
+  HXT_CHECK( hxt_boundary_recovery(mesh) );
+  return HXT_STATUS_OK;
+}
+
+int main(int argc, char** argv) {
+
+  const char* input = NULL;
+  const char* output = NULL;
+  const char* geoFile = NULL;
+
+  HXTTetMeshOptions options = {.refine=1, .optimize=1, .verbosity=1, .qualityMin=0.35, .recoveryFun=recoveryFun};
+
+  HXT_CHECK( hxtAddOption('t', "omp_num_threads",
+                          "Number of threads used for parallel work.\n"
+                          "If NUM<=0, use OMP_NUM_THREADS environment variable", HXT_INT, NULL, &options.defaultThreads));
+  HXT_CHECK( hxtAddOption('d', "delaunay_threads",
+                              "Overrides the maximum number of threads for Delaunay insertion\n"
+                              " * NUM>0: use NUM threads\n"
+                              " * NUM=0: use the default nbr. of threads (see `-t` option)\n"
+                              " * NUM<0: use OMP_NUM_PROCS", HXT_INT, NULL, &options.delaunayThreads));
+  HXT_CHECK( hxtAddOption('o', "opti_threads",
+                              "Overrides the maximum number of threads for mesh optimizations\n"
+                              " * NUM>0: use NUM threads\n"
+                              " * NUM=0: use the default nbr. of threads (see `-t` option)\n"
+                              " * NUM<0: use OMP_NUM_PROCS", HXT_INT, NULL, &options.improveThreads));
+  HXT_CHECK( hxtAddOption('r', "reproducible",
+                          "Reproducible mesh:\n"
+                          "The output mesh will be identical with this option\n"
+                          "if given\n"
+                          " - the same vertices in the same order\n"
+                          " - the same number of threads\n"
+                          "WARNING: This option slows down the mesh generation\n"
+                          "except with 1 thread", HXT_FLAG, NULL, &options.reproducible));
+  HXT_CHECK( hxtAddOption('v', "verbosity",
+                       "Verbosity level of output messages\n"
+                       " * NUM=0: print no information\n"
+                       " * NUM=1: print some information\n"
+                       " * NUM=2: print all information", HXT_INT, &HXT_0_2_RANGE, &options.verbosity));
+  HXT_CHECK( hxtAddOption('s', "stat", "Print timing for each portion of the program", HXT_FLAG, NULL, &options.stat));
+  HXT_CHECK( hxtAddOption('n', "no-refinement", "Do not refine the mesh => no vertices are added", HXT_NO_FLAG, NULL, &options.refine));
+  HXT_CHECK( hxtAddOption('N', "no-improvement", "Do not optimize the mesh quality", HXT_NO_FLAG, NULL, &options.optimize) );
+  HXT_CHECK( hxtAddOption('a', "aspect-ratio-min", "The threshold on the aspect-ratio used during the optimization", HXT_DOUBLE, &HXT_0_1_RANGE, &options.qualityMin));
+
+  const HXTOptionArgumentConstraints geoSuffix = {.stringSuffix=".geo"};
+  HXT_CHECK( hxtAddOption('g', "generate-geo", "Write a .geo file that describe the volumes from the input surface mesh", HXT_ASK_TO_ERASE_FILENAME, &geoSuffix, &geoFile));
+
+  HXT_CHECK( hxtAddTrailingOption("INPUT_FILE", HXT_EXISTING_FILENAME, NULL, &input));
+  HXT_CHECK( hxtAddTrailingOption("OUTPUT_FILE", HXT_STRING, NULL, &output));
+
+  HXT_PARSE_COMMAND_LINE(argc, argv,
+                         "hxtMesh3d",
+                         "Compute a mesh from the surface mesh in INPUT_FILE",
+                         "--\nContact: celestin.marot@uclouvain.be");
+
+  if(options.verbosity)
+  {
+    const char* T = "true";
+    const char* F = "false";
+    printf("\ninput:             %s\noutput:            %s\n"
+             "Number of threads: %d\nDelaunay threads:  %d\nOptim. threads:    %d\n"
+             "reproducible:      %s\nverbosity level:   %d\nshow statistics:   %s\n"
+             "refine:            %s\noptimize :         %s\nmin aspect ratio:  %.3f\n\n",
+           input?input:"-", output?output:"-", options.defaultThreads<=0?omp_get_max_threads():options.defaultThreads,
+           options.delaunayThreads, options.improveThreads,
+           options.reproducible?T:F, (int) options.verbosity, options.stat?T:F, options.refine?T:F, options.optimize?T:F, options.qualityMin);
+  }
+
+
+  /*******************  ^ all argument were processed *********************/
+  HXTMesh *mesh;
+  HXT_CHECK( hxtMeshCreate(&mesh) );
+
+  HXT_INFO_COND(options.verbosity>0, "Reading \"%s\"\n", input);
+  HXT_CHECK( hxtMeshReadGmsh(mesh, input) );
+  
+  HXT_CHECK( hxtTetMesh(mesh, &options) );
+  
+  if(output){
+    HXT_INFO_COND(options.verbosity>0, "Writing result to \"%s\"", output);
+    HXT_CHECK(hxtMeshWriteGmsh(mesh, output));
+  }
+
+  if(geoFile) {
+    // generate a .geo file
+    HXT_INFO_COND(options.verbosity>0, "Writing .geo file to \"%s\"", geoFile);
+    FILE* fp = fopen(geoFile, "w");
+    fprintf(fp, "Merge \"%s\"; // loads the 2d mesh of the volume\n", input);
+
+    uint16_t surf = 0;
+    for(uint16_t i=0; i<mesh->brep.numVolumes; i++) {
+      fprintf(fp, "Surface Loop(%u) = {%u", i+1, mesh->brep.surfacesPerVolume[surf++]);
+      for(uint16_t j=1; j<mesh->brep.numSurfacesPerVolume[i]; j++) {
+        fprintf(fp, ",%u", mesh->brep.surfacesPerVolume[surf++]);
+      }
+      fprintf(fp, "};\nVolume(%u) = {%u};\n", i+1, i+1);
+    }
+    fclose(fp);
+  }
+
+  HXT_CHECK( hxtMeshDelete(&mesh) );
+  return HXT_STATUS_OK;
+}
diff --git a/contrib/hxt/tetMesh/exe/tetOpti_CLI.c b/contrib/hxt/tetMesh/exe/tetOpti_CLI.c
new file mode 100644
index 0000000000000000000000000000000000000000..7772044f9962b267ee75e528963654dbc171de3b
--- /dev/null
+++ b/contrib/hxt/tetMesh/exe/tetOpti_CLI.c
@@ -0,0 +1,103 @@
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
+#include "hxt_tetOpti.h"
+#include "hxt_tetRepair.h"
+#include "hxt_tetFlag.h"
+#include "hxt_opt.h"
+#include "hxt_tools.h"
+#include "hxt_omp.h"
+
+int main(int argc, char** argv) {
+
+  const char* input = NULL;
+  const char* output = NULL;
+
+  int maxThreads = 0;
+
+  HXTOptimizeOptions options = {.qualityMin=0.35, .reproducible=1, .verbosity=2};
+
+  HXT_CHECK( hxtAddOption('t', "omp_num_threads",
+                          "Number of threads used for parallel work.\n"
+                          "If NUM<=0, use OMP_NUM_THREADS environment variable", HXT_INT, NULL, &maxThreads));
+  HXT_CHECK( hxtAddOption('o', "opti_threads",
+                              "Overrides the maximum number of threads for mesh improvement\n"
+                              " * NUM>0: use NUM threads\n"
+                              " * NUM=0: use the default nbr. of threads (see `-t` option)\n"
+                              " * NUM<0: use OMP_NUM_PROCS", HXT_INT, NULL, &options.numThreads));
+  HXT_CHECK( hxtAddOption('v', "verbosity",
+                       "Verbosity level of output messages\n"
+                       " * NUM=0: print no information\n"
+                       " * NUM=1: print some information\n"
+                       " * NUM=2: print all information", HXT_INT, &HXT_0_2_RANGE, &options.verbosity));
+  HXT_CHECK( hxtAddOption('a', "aspect-ratio-min", "The threshold on the aspect-ratio used during the optimization", HXT_DOUBLE, &HXT_0_1_RANGE, &options.qualityMin));
+
+  HXT_CHECK( hxtAddTrailingOption("INPUT_FILE", HXT_EXISTING_FILENAME, NULL, &input));
+  HXT_CHECK( hxtAddTrailingOption("OUTPUT_FILE", HXT_STRING, NULL, &output));
+
+  HXT_PARSE_COMMAND_LINE(argc, argv,
+                         "hxtTetOpti",
+                         "Improve an existing tet mesh",
+                         "--\nContact: celestin.marot@uclouvain.be");
+
+  if(maxThreads>0) {
+    omp_set_num_threads(maxThreads);
+  }
+
+  /*******************  ^ all argument were processed *********************/
+  HXTMesh *mesh;
+  HXT_CHECK( hxtMeshCreate(&mesh) );
+
+  HXT_INFO_COND(options.verbosity>0, "Reading \"%s\"\n", input);
+  HXT_CHECK( hxtMeshReadGmsh(mesh, input) );
+  HXT_INFO("%u points, %" HXTu64 " tets", mesh->vertices.num, mesh->tetrahedra.num);
+
+  if(mesh->tetrahedra.num==0)
+    return HXT_ERROR_MSG(HXT_STATUS_ERROR, "No tetrahedron to optimize");
+
+  HXT_INFO("Computing adjacencies");
+  HXT_CHECK( hxtTetAdjacencies(mesh) );
+
+#ifdef DEBUG
+  HXT_CHECK( hxtTetVerify(mesh) );
+#endif
+
+  HXT_INFO("Creating mesh->tetrahedra.flag");
+  HXT_CHECK( hxtAlignedMalloc(&mesh->tetrahedra.flag, sizeof(uint16_t) * mesh->tetrahedra.size) );
+
+  HXT_INFO("Initializing flags and setting constraint");
+  #pragma omp parallel for
+  for(uint64_t i=0; i<mesh->tetrahedra.num; i++) {
+    mesh->tetrahedra.flag[i] = 0;
+    for(int j=0; j<4; j++) {
+      if(mesh->tetrahedra.neigh[4*i+j]==HXT_NO_ADJACENT)
+        setFacetConstraint(mesh, i, j);
+    }
+  }
+
+#ifdef DEBUG
+  HXT_CHECK( hxtTetVerify(mesh) );
+#endif
+
+
+  HXT_INFO("Improving the quality of bad tet.");
+  HXT_CHECK( hxtOptimizeTetrahedra(mesh, &options) );
+
+#ifdef DEBUG
+  HXT_CHECK( hxtTetVerify(mesh) );
+#endif
+  
+  
+  if(output){
+    HXT_INFO_COND(options.verbosity>0, "Writing result to \"%s\"", output);
+    HXT_CHECK(hxtMeshWriteGmsh(mesh, output));
+  }
+
+  HXT_CHECK( hxtMeshDelete(&mesh) );
+  return HXT_STATUS_OK;
+}
diff --git a/contrib/hxt/tetMesh/src/hxt_tetDelaunay.h b/contrib/hxt/tetMesh/include/hxt_tetDelaunay.h
similarity index 97%
rename from contrib/hxt/tetMesh/src/hxt_tetDelaunay.h
rename to contrib/hxt/tetMesh/include/hxt_tetDelaunay.h
index 885cc79d0e433de9fa62adc2e268b8fb8090d5a6..70093ed7a6a9d0d7e6d7b396ef88d9c57536d5c2 100644
--- a/contrib/hxt/tetMesh/src/hxt_tetDelaunay.h
+++ b/contrib/hxt/tetMesh/include/hxt_tetDelaunay.h
@@ -13,7 +13,9 @@
 extern "C" {
 #endif
 
-#include "hxt_tetPartition.h"
+#include "hxt_mesh.h"
+#include "hxt_vertices.h"
+#include "hxt_bbox.h"
 
 /**
 * \file hxt_tetDelaunay.h Delaunay tetrahedrization
@@ -136,9 +138,6 @@ HXTStatus hxtDelaunay(HXTMesh* mesh, HXTDelaunayOptions* options);
 // HXTStatus hxtDelaunayFreeBuffer(void** buffer);
 
 
-HXTStatus walking2Cavity(HXTMesh* mesh, HXTPartition* partition, uint64_t* __restrict__ curTet, const uint32_t vta);
-
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/contrib/hxt/tetMesh/src/hxt_tetFlag.h b/contrib/hxt/tetMesh/include/hxt_tetFlag.h
similarity index 100%
rename from contrib/hxt/tetMesh/src/hxt_tetFlag.h
rename to contrib/hxt/tetMesh/include/hxt_tetFlag.h
diff --git a/contrib/hxt/tetMesh/src/hxt_tetOpti.h b/contrib/hxt/tetMesh/include/hxt_tetOpti.h
similarity index 100%
rename from contrib/hxt/tetMesh/src/hxt_tetOpti.h
rename to contrib/hxt/tetMesh/include/hxt_tetOpti.h
diff --git a/contrib/hxt/tetMesh/src/hxt_tetRepair.h b/contrib/hxt/tetMesh/include/hxt_tetRepair.h
similarity index 100%
rename from contrib/hxt/tetMesh/src/hxt_tetRepair.h
rename to contrib/hxt/tetMesh/include/hxt_tetRepair.h
diff --git a/contrib/hxt/tetMesh/src/hxt_vertices.h b/contrib/hxt/tetMesh/include/hxt_vertices.h
similarity index 100%
rename from contrib/hxt/tetMesh/src/hxt_vertices.h
rename to contrib/hxt/tetMesh/include/hxt_vertices.h
diff --git a/contrib/hxt/tetMesh/src/HXTSPR.c b/contrib/hxt/tetMesh/src/HXTSPR.c
index 25073f1f34b4c771a4dee2b4b53e08b090224b7c..1e8966fd3387cbac5c057f5ee9e419bb45f67315 100644
--- a/contrib/hxt/tetMesh/src/HXTSPR.c
+++ b/contrib/hxt/tetMesh/src/HXTSPR.c
@@ -7,7 +7,7 @@
 //   Célestin Marot
 
 #include "HXTSPR.h"
-#include <math.h>
+#include "hxt_tetOptiUtils.h"
 #include "hxt_tetFlag.h"
 #include "predicates.h"
 
diff --git a/contrib/hxt/tetMesh/src/hxt_tetDelaunay.c b/contrib/hxt/tetMesh/src/hxt_tetDelaunay.c
index 263239aca99e2466a620684b0f7a800bcca5e1e2..8816d9e94023370cf0bfb9d94f0eb28d7a73b433 100644
--- a/contrib/hxt/tetMesh/src/hxt_tetDelaunay.c
+++ b/contrib/hxt/tetMesh/src/hxt_tetDelaunay.c
@@ -7,6 +7,7 @@
 //   Célestin Marot
 
 #include "hxt_tetDelaunay.h"
+#include "hxt_tetPartition.h"
 #include "predicates.h"
 #include "hxt_tetSync.h"
 #include "hxt_tetFlag.h"
@@ -505,7 +506,7 @@ static int tetInsphere(HXTMesh* mesh, const uint64_t curTet, const uint32_t vta)
 /***********************************
  * walk to cavity
  ***********************************/
-HXTStatus walking2Cavity(HXTMesh* mesh, HXTPartition* partition, uint64_t* __restrict__ curTet, const uint32_t vta)
+static inline HXTStatus walking2Cavity(HXTMesh* mesh, HXTPartition* partition, uint64_t* __restrict__ curTet, const uint32_t vta)
 {
   uint64_t nextTet = *curTet;
   HXTVertex* vertices = (HXTVertex*) mesh->vertices.coord;
@@ -1275,6 +1276,7 @@ static HXTStatus insertion(HXT2Sync* shared2sync,
 
   if(local->ball.num > local->deleted.num){
     HXT_CHECK( createNewDeleted(shared2sync, &local->deleted, local->ball.num) );
+    HXT_ASSERT(local->deleted.num >= local->ball.num);
   }
 
   HXT_CHECK( fillingACavity(mesh, local, verticesID, curTet, vta, color) );
diff --git a/contrib/hxt/tetMesh/src/hxt_tetNodalSize.c b/contrib/hxt/tetMesh/src/hxt_tetNodalSize.c
index e0f17e1ac32747dc295425ee74c6d7fabff0e703..acab5f1b1db1c48dfcf43e376f899a471cc3babb 100644
--- a/contrib/hxt/tetMesh/src/hxt_tetNodalSize.c
+++ b/contrib/hxt/tetMesh/src/hxt_tetNodalSize.c
@@ -7,7 +7,6 @@
 //   Célestin Marot
 
 #include "hxt_vertices.h"
-#include <math.h>
 
 HXTStatus hxtCreateNodalSize(HXTMesh* mesh, double** nodalSizes_ptr)
 {
diff --git a/contrib/hxt/tetMesh/src/hxt_tetNodalSize.h b/contrib/hxt/tetMesh/src/hxt_tetNodalSize.h
index 46a3d64ab2a95d31df49d0d9fe3a7492794dc424..b0cc072c2d4e1179d2715bc0811c9965d922ce4b 100644
--- a/contrib/hxt/tetMesh/src/hxt_tetNodalSize.h
+++ b/contrib/hxt/tetMesh/src/hxt_tetNodalSize.h
@@ -12,7 +12,7 @@
 #include "hxt_mesh.h"
 
 HXTStatus hxtCreateNodalSize(HXTMesh* mesh, double** nodalSizes_ptr);
-HXTStatus hxtDestroyNodalsize(double** nodalSize);
+HXTStatus hxtDestroyNodalSize(double** nodalSize);
 
 /// Compute sizes at vertices of the mesh from meshSizeFun
 HXTStatus hxtComputeNodalSizeFromFunction(HXTMesh* mesh, double* nodalSize,
@@ -21,8 +21,8 @@ HXTStatus hxtComputeNodalSizeFromFunction(HXTMesh* mesh, double* nodalSize,
                                           void* meshSizeData);
 
 /// Compute sizes at vertices of the mesh from existing edges
-HXTStatus hxtComputeNodalsizeFromTrianglesAndLines(HXTMesh* mesh, double* nodalSize);
-HXTStatus hxtComputeNodalsizeFromMesh(HXTMesh* mesh, double* nodalSize);
+HXTStatus hxtComputeNodalSizeFromTrianglesAndLines(HXTMesh* mesh, double* nodalSize);
+HXTStatus hxtComputeNodalSizeFromMesh(HXTMesh* mesh, double* nodalSize);
 
 
 
diff --git a/contrib/hxt/tetMesh/src/hxt_tetOptiUtils.h b/contrib/hxt/tetMesh/src/hxt_tetOptiUtils.h
index fedf57f2e9c411d2b51124e5abe24e0b4ded0f7b..c5baec79724a05568d7a68ca462841cb07263300 100644
--- a/contrib/hxt/tetMesh/src/hxt_tetOptiUtils.h
+++ b/contrib/hxt/tetMesh/src/hxt_tetOptiUtils.h
@@ -36,7 +36,7 @@ typedef struct {
 } Statistic;
 
 
-typedef struct 
+typedef struct
 {
   /*** located here ***/
   // list of deleted tet. Added when the cavity is created, removed when the cavity is filled
diff --git a/contrib/hxt/tetMesh/src/hxt_tetQuality.c b/contrib/hxt/tetMesh/src/hxt_tetQuality.c
index 31b876c3f07e67f75c00ce48cfc018d1429765f5..0b8427d7f7db153ed0dcba80c93624ab5f9cbd48 100644
--- a/contrib/hxt/tetMesh/src/hxt_tetQuality.c
+++ b/contrib/hxt/tetMesh/src/hxt_tetQuality.c
@@ -6,7 +6,6 @@
 // Contributor(s):
 //   Célestin Marot
 
-#include <math.h>
 #include "hxt_tools.h"
 
 //!\ this function does not return the aspect ratio 'r'. It returns 'r^2/24'
diff --git a/contrib/hxt/tetMesh/src/hxt_tetRefine.c b/contrib/hxt/tetMesh/src/hxt_tetRefine.c
index e6be20467a5e5dc2e2b11a6ac1d16e151a0313ae..6f2c1faa16f000f6f840d0b706ff70b657270659 100644
--- a/contrib/hxt/tetMesh/src/hxt_tetRefine.c
+++ b/contrib/hxt/tetMesh/src/hxt_tetRefine.c
@@ -6,7 +6,6 @@
 // Contributor(s):
 //   Célestin Marot
 
-#include <math.h>
 #include "hxt_tetDelaunay.h"
 #include "predicates.h"
 #include "hxt_tetFlag.h"
diff --git a/contrib/hxt/tetMesh/src/hxt_tetSync.c b/contrib/hxt/tetMesh/src/hxt_tetSync.c
index 2458194f712fc7fd57486a667ba6a0aa9065d671..91551a7f693a1b58b17d5b3e92beaa1d58c95ee0 100644
--- a/contrib/hxt/tetMesh/src/hxt_tetSync.c
+++ b/contrib/hxt/tetMesh/src/hxt_tetSync.c
@@ -101,6 +101,6 @@ HXTStatus createNewDeleted(HXT2Sync* shared,
   }
 
   deleted->createdNew = 1;
-  deleted->num = DELETED_BUFFER_SIZE;
+  deleted->num += needed;
   return HXT_STATUS_OK;
 }
\ No newline at end of file
diff --git a/contrib/hxt/tetMesh/src/hxt_vertices.c b/contrib/hxt/tetMesh/src/hxt_vertices.c
index 09c34bc45a6ef93ca91f18fbefd2f538d9d01c73..76b93ac40f85cb418042bd9afa441a4badbc462d 100644
--- a/contrib/hxt/tetMesh/src/hxt_vertices.c
+++ b/contrib/hxt/tetMesh/src/hxt_vertices.c
@@ -7,9 +7,10 @@
 //   Célestin Marot
 
 #include "hxt_omp.h"
-#include <string.h>
 #include "hxt_vertices.h"
 #include "hxt_sort.h"
+#include <string.h>
+
 
 #if defined( __BMI2__ ) || defined( __AVX2__ ) || (defined(__AVX512F__) && defined(__AVX512VL__))
 #include <immintrin.h>