From f0bcc41c2b73d88d82c45cbd5d828070eaceccb6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9lestin=20Marot?= <celestin.marot@uclouvain.be>
Date: Tue, 21 Apr 2020 10:20:34 +0200
Subject: [PATCH] update hxt:

The *hxt* standalone repos that we are maintaining on a private Gitlab
is becoming a total mess IMO. Therefore, as I'm at the end of my
thesis and I want to distribute the *hxt* library in a "clean" manner,
I thought I could maybe clean the *hxt* directory in *contrib*, and
make it so that we can compile things independently. Therefore, I
created this huge commit.

 - Keep a directory structure, even if it is in contrib.
   Each part of *hxt* has its own CMakeList.txt, and is compiled
   by gmsh as an OBJECT library target.
   Each target can be separately compiled.
   For example, you can go in *contrib/hxt/tetMesh* and do
   `mkdir build && cd build && cmake .. && make -j4`
 - Files that were not used by gmsh were deleted.
   Metis was actually not used.
 - tetMesh was updated to the newest version
 - hxt_octree.cpp was almost entirely surrounded by `#ifdef HAVE_P4EST`
   and it was throwing an error if it wasn't the case
   Therefore, I change that so that HAVE_P4EST was a prerequisite for
   the compilation.
 - You might notice cmake_minimum_required in *hxt* is version 3.9
   to enable target_compile_features(... c_std_99)
   I doubt that people who wants to have HXT_ENABLED AND
   have a compiler with OpenMP 4+ and C99 AND have the latest version
   of Gmsh will have problem installing a newer version of CMake.
---
 CMakeLists.txt                                |   49 +-
 Geo/GModelParametrize.cpp                     |    5 +-
 Geo/discreteFace.cpp                          |    5 +-
 Mesh/automaticMeshSizeField.cpp               |    5 +-
 Mesh/automaticMeshSizeField.h                 |    2 +-
 Mesh/meshGRegionHxt.cpp                       |    7 +-
 contrib/hxt/CMakeLists.txt                    |   65 -
 contrib/hxt/CREDITS.txt                       |   10 +-
 contrib/hxt/core/CMakeLists.txt               |   50 +
 contrib/hxt/{ => core/include}/hxt_bbox.h     |   16 +-
 contrib/hxt/{ => core/include}/hxt_mesh.h     |   51 +-
 contrib/hxt/{ => core/include}/hxt_message.h  |   90 +-
 contrib/hxt/{ => core/include}/hxt_omp.h      |    0
 contrib/hxt/{ => core/include}/hxt_sort.h     |   55 +-
 contrib/hxt/{ => core/include}/hxt_tools.h    |   54 +-
 contrib/hxt/{ => core/src}/hxt_bbox.c         |    8 +
 contrib/hxt/{ => core/src}/hxt_mesh.c         |  177 +-
 contrib/hxt/{ => core/src}/hxt_message.c      |    9 +
 contrib/hxt/{ => core/src}/hxt_sort.c         |    8 +
 contrib/hxt/hxt_api.h                         |  118 --
 contrib/hxt/hxt_bissection.c                  |  458 ----
 contrib/hxt/hxt_bissection.h                  |   11 -
 contrib/hxt/hxt_boundary_recovery.h           |    4 -
 contrib/hxt/hxt_context.c                     |   19 -
 contrib/hxt/hxt_context.h                     |    9 -
 contrib/hxt/hxt_edgeRemoval.h                 |   43 -
 contrib/hxt/hxt_laplace.c                     |  159 --
 contrib/hxt/hxt_laplace.h                     |    8 -
 contrib/hxt/hxt_mesh3d.c                      |  424 ----
 contrib/hxt/hxt_mesh3d.h                      |   28 -
 contrib/hxt/hxt_mesh3d_main.c                 |  166 --
 contrib/hxt/hxt_mesh3d_main.h                 |   20 -
 contrib/hxt/hxt_mesh_size.c                   |  145 --
 contrib/hxt/hxt_mesh_size.h                   |   18 -
 contrib/hxt/hxt_octree_api.h                  |   53 -
 contrib/hxt/hxt_opt.c                         |  812 -------
 contrib/hxt/hxt_opt.h                         |  170 --
 contrib/hxt/hxt_option.c                      |  504 -----
 contrib/hxt/hxt_option.h                      |  182 --
 contrib/hxt/hxt_parametrization.c             |  754 -------
 contrib/hxt/hxt_parametrization.h             |   17 -
 contrib/hxt/hxt_tetOpti.c                     |  819 -------
 contrib/hxt/hxt_tetOptiDate.h                 |   19 -
 contrib/hxt/hxt_tetPartition.h                |   35 -
 contrib/hxt/hxt_tetPostpro.c                  |  182 --
 contrib/hxt/hxt_tetPostpro.h                  |   32 -
 contrib/hxt/hxt_tetQuality.c                  |  254 ---
 contrib/hxt/hxt_tet_aspect_ratio.c            |  192 --
 contrib/hxt/hxt_tet_aspect_ratio.h            |    9 -
 contrib/hxt/hxt_tetrahedra.c                  | 1882 -----------------
 contrib/hxt/hxt_tetrahedra.h                  |  113 -
 contrib/hxt/hxt_tools.c                       |  138 --
 contrib/hxt/laplace_main.c                    |   16 -
 contrib/hxt/predicates.h                      |   72 -
 contrib/hxt/predicates/CMakeLists.txt         |   32 +
 contrib/hxt/predicates/include/predicates.h   |   98 +
 contrib/hxt/{ => predicates/src}/predicates.c |  477 ++---
 contrib/hxt/reparam/CMakeLists.txt            |   46 +
 contrib/hxt/reparam/cmake/FindPETSc.cmake     |  119 ++
 .../hxt/{ => reparam/include}/hxt_curvature.h |    0
 contrib/hxt/{ => reparam/include}/hxt_edge.h  |    2 -
 .../{ => reparam/include}/hxt_linear_system.h |    3 +-
 .../{ => reparam/include}/hxt_mean_values.h   |    3 +
 .../hxt/{ => reparam/src}/hxt_class_macro.h   |    0
 contrib/hxt/{ => reparam/src}/hxt_curvature.c |   53 +-
 contrib/hxt/{ => reparam/src}/hxt_edge.c      |    9 +-
 .../hxt/{ => reparam/src}/hxt_linear_system.c |    5 +
 .../{ => reparam/src}/hxt_linear_system_lu.c  |  144 +-
 .../{ => reparam/src}/hxt_linear_system_lu.h  |    3 +-
 .../src}/hxt_linear_system_petsc.c            |   65 +-
 .../src}/hxt_linear_system_petsc.h            |    3 +-
 .../hxt/{ => reparam/src}/hxt_mean_values.c   |   11 +-
 .../{ => reparam/src}/hxt_non_linear_solver.c |    3 +-
 .../{ => reparam/src}/hxt_non_linear_solver.h |    1 -
 contrib/hxt/sizeField/CMakeLists.txt          |   15 +
 contrib/hxt/{ => sizeField}/hxt_octree.cpp    |   26 +-
 contrib/hxt/{ => sizeField}/hxt_octree.h      |    4 -
 contrib/hxt/tetBR/CMakeLists.txt              |   28 +
 .../hxt/tetBR/include/hxt_boundary_recovery.h |   16 +
 .../{ => tetBR/src}/hxt_boundary_recovery.cxx |  113 +-
 contrib/hxt/{ => tetBR/src}/tetgenBR.cxx      |    0
 contrib/hxt/{ => tetBR/src}/tetgenBR.h        |    2 +-
 contrib/hxt/tetMesh/CMakeLists.txt            |   59 +
 .../hxt/{ => tetMesh/include}/hxt_tetMesh.h   |   14 +-
 contrib/hxt/{ => tetMesh/src}/HXTSPR.c        |  198 +-
 contrib/hxt/{ => tetMesh/src}/HXTSPR.h        |   65 +-
 .../hxt/{ => tetMesh/src}/hxt_edgeRemoval.c   |  185 +-
 contrib/hxt/tetMesh/src/hxt_edgeRemoval.h     |   26 +
 contrib/hxt/{ => tetMesh/src}/hxt_smoothing.c |   52 +-
 contrib/hxt/{ => tetMesh/src}/hxt_smoothing.h |   31 +-
 contrib/hxt/{ => tetMesh/src}/hxt_tetColor.c  |    8 +
 contrib/hxt/{ => tetMesh/src}/hxt_tetColor.h  |   12 +-
 .../hxt/{ => tetMesh/src}/hxt_tetDelaunay.c   |  594 ++++--
 .../hxt/{ => tetMesh/src}/hxt_tetDelaunay.h   |   14 +-
 contrib/hxt/{ => tetMesh/src}/hxt_tetFlag.c   |   10 +-
 contrib/hxt/{ => tetMesh/src}/hxt_tetFlag.h   |   19 +-
 contrib/hxt/{ => tetMesh/src}/hxt_tetMesh.c   |   36 +-
 .../hxt/{ => tetMesh/src}/hxt_tetNodalSize.c  |    9 +
 .../hxt/{ => tetMesh/src}/hxt_tetNodalSize.h  |   12 +-
 contrib/hxt/tetMesh/src/hxt_tetOpti.c         |  724 +++++++
 contrib/hxt/{ => tetMesh/src}/hxt_tetOpti.h   |   22 +-
 contrib/hxt/tetMesh/src/hxt_tetOptiUtils.h    |   68 +
 contrib/hxt/tetMesh/src/hxt_tetPartition.h    |   66 +
 contrib/hxt/tetMesh/src/hxt_tetQuality.c      |   70 +
 .../hxt/{ => tetMesh/src}/hxt_tetQuality.h    |   26 +-
 contrib/hxt/{ => tetMesh/src}/hxt_tetRefine.c |  390 ++--
 contrib/hxt/{ => tetMesh/src}/hxt_tetRefine.h |   15 +-
 contrib/hxt/{ => tetMesh/src}/hxt_tetRepair.c |  176 +-
 contrib/hxt/{ => tetMesh/src}/hxt_tetRepair.h |   12 +-
 contrib/hxt/{ => tetMesh/src}/hxt_tetSync.c   |   12 +-
 contrib/hxt/{ => tetMesh/src}/hxt_tetSync.h   |   13 +-
 contrib/hxt/{ => tetMesh/src}/hxt_tetUtils.c  |   13 +-
 contrib/hxt/{ => tetMesh/src}/hxt_tetUtils.h  |   13 +-
 contrib/hxt/{ => tetMesh/src}/hxt_vertices.c  |    8 +
 contrib/hxt/{ => tetMesh/src}/hxt_vertices.h  |   12 +-
 115 files changed, 3317 insertions(+), 9499 deletions(-)
 delete mode 100644 contrib/hxt/CMakeLists.txt
 create mode 100644 contrib/hxt/core/CMakeLists.txt
 rename contrib/hxt/{ => core/include}/hxt_bbox.h (90%)
 rename contrib/hxt/{ => core/include}/hxt_mesh.h (79%)
 rename contrib/hxt/{ => core/include}/hxt_message.h (53%)
 rename contrib/hxt/{ => core/include}/hxt_omp.h (100%)
 rename contrib/hxt/{ => core/include}/hxt_sort.h (97%)
 rename contrib/hxt/{ => core/include}/hxt_tools.h (81%)
 rename contrib/hxt/{ => core/src}/hxt_bbox.c (92%)
 rename contrib/hxt/{ => core/src}/hxt_mesh.c (82%)
 rename contrib/hxt/{ => core/src}/hxt_message.c (96%)
 rename contrib/hxt/{ => core/src}/hxt_sort.c (93%)
 delete mode 100644 contrib/hxt/hxt_api.h
 delete mode 100644 contrib/hxt/hxt_bissection.c
 delete mode 100644 contrib/hxt/hxt_bissection.h
 delete mode 100644 contrib/hxt/hxt_boundary_recovery.h
 delete mode 100644 contrib/hxt/hxt_context.c
 delete mode 100644 contrib/hxt/hxt_context.h
 delete mode 100644 contrib/hxt/hxt_edgeRemoval.h
 delete mode 100644 contrib/hxt/hxt_laplace.c
 delete mode 100644 contrib/hxt/hxt_laplace.h
 delete mode 100644 contrib/hxt/hxt_mesh3d.c
 delete mode 100644 contrib/hxt/hxt_mesh3d.h
 delete mode 100644 contrib/hxt/hxt_mesh3d_main.c
 delete mode 100644 contrib/hxt/hxt_mesh3d_main.h
 delete mode 100644 contrib/hxt/hxt_mesh_size.c
 delete mode 100644 contrib/hxt/hxt_mesh_size.h
 delete mode 100644 contrib/hxt/hxt_octree_api.h
 delete mode 100644 contrib/hxt/hxt_opt.c
 delete mode 100644 contrib/hxt/hxt_opt.h
 delete mode 100644 contrib/hxt/hxt_option.c
 delete mode 100644 contrib/hxt/hxt_option.h
 delete mode 100644 contrib/hxt/hxt_parametrization.c
 delete mode 100644 contrib/hxt/hxt_parametrization.h
 delete mode 100644 contrib/hxt/hxt_tetOpti.c
 delete mode 100644 contrib/hxt/hxt_tetOptiDate.h
 delete mode 100644 contrib/hxt/hxt_tetPartition.h
 delete mode 100644 contrib/hxt/hxt_tetPostpro.c
 delete mode 100644 contrib/hxt/hxt_tetPostpro.h
 delete mode 100644 contrib/hxt/hxt_tetQuality.c
 delete mode 100644 contrib/hxt/hxt_tet_aspect_ratio.c
 delete mode 100644 contrib/hxt/hxt_tet_aspect_ratio.h
 delete mode 100644 contrib/hxt/hxt_tetrahedra.c
 delete mode 100644 contrib/hxt/hxt_tetrahedra.h
 delete mode 100644 contrib/hxt/hxt_tools.c
 delete mode 100644 contrib/hxt/laplace_main.c
 delete mode 100644 contrib/hxt/predicates.h
 create mode 100644 contrib/hxt/predicates/CMakeLists.txt
 create mode 100644 contrib/hxt/predicates/include/predicates.h
 rename contrib/hxt/{ => predicates/src}/predicates.c (89%)
 create mode 100644 contrib/hxt/reparam/CMakeLists.txt
 create mode 100644 contrib/hxt/reparam/cmake/FindPETSc.cmake
 rename contrib/hxt/{ => reparam/include}/hxt_curvature.h (100%)
 rename contrib/hxt/{ => reparam/include}/hxt_edge.h (97%)
 rename contrib/hxt/{ => reparam/include}/hxt_linear_system.h (98%)
 rename contrib/hxt/{ => reparam/include}/hxt_mean_values.h (95%)
 rename contrib/hxt/{ => reparam/src}/hxt_class_macro.h (100%)
 rename contrib/hxt/{ => reparam/src}/hxt_curvature.c (81%)
 rename contrib/hxt/{ => reparam/src}/hxt_edge.c (98%)
 rename contrib/hxt/{ => reparam/src}/hxt_linear_system.c (96%)
 rename contrib/hxt/{ => reparam/src}/hxt_linear_system_lu.c (77%)
 rename contrib/hxt/{ => reparam/src}/hxt_linear_system_lu.h (98%)
 rename contrib/hxt/{ => reparam/src}/hxt_linear_system_petsc.c (88%)
 rename contrib/hxt/{ => reparam/src}/hxt_linear_system_petsc.h (98%)
 rename contrib/hxt/{ => reparam/src}/hxt_mean_values.c (99%)
 rename contrib/hxt/{ => reparam/src}/hxt_non_linear_solver.c (99%)
 rename contrib/hxt/{ => reparam/src}/hxt_non_linear_solver.h (98%)
 create mode 100644 contrib/hxt/sizeField/CMakeLists.txt
 rename contrib/hxt/{ => sizeField}/hxt_octree.cpp (99%)
 rename contrib/hxt/{ => sizeField}/hxt_octree.h (98%)
 create mode 100644 contrib/hxt/tetBR/CMakeLists.txt
 create mode 100644 contrib/hxt/tetBR/include/hxt_boundary_recovery.h
 rename contrib/hxt/{ => tetBR/src}/hxt_boundary_recovery.cxx (91%)
 rename contrib/hxt/{ => tetBR/src}/tetgenBR.cxx (100%)
 rename contrib/hxt/{ => tetBR/src}/tetgenBR.h (99%)
 create mode 100644 contrib/hxt/tetMesh/CMakeLists.txt
 rename contrib/hxt/{ => tetMesh/include}/hxt_tetMesh.h (93%)
 rename contrib/hxt/{ => tetMesh/src}/HXTSPR.c (91%)
 rename contrib/hxt/{ => tetMesh/src}/HXTSPR.h (79%)
 rename contrib/hxt/{ => tetMesh/src}/hxt_edgeRemoval.c (77%)
 create mode 100644 contrib/hxt/tetMesh/src/hxt_edgeRemoval.h
 rename contrib/hxt/{ => tetMesh/src}/hxt_smoothing.c (84%)
 rename contrib/hxt/{ => tetMesh/src}/hxt_smoothing.h (50%)
 rename contrib/hxt/{ => tetMesh/src}/hxt_tetColor.c (99%)
 rename contrib/hxt/{ => tetMesh/src}/hxt_tetColor.h (82%)
 rename contrib/hxt/{ => tetMesh/src}/hxt_tetDelaunay.c (82%)
 rename contrib/hxt/{ => tetMesh/src}/hxt_tetDelaunay.h (94%)
 rename contrib/hxt/{ => tetMesh/src}/hxt_tetFlag.c (98%)
 rename contrib/hxt/{ => tetMesh/src}/hxt_tetFlag.h (97%)
 rename contrib/hxt/{ => tetMesh/src}/hxt_tetMesh.c (86%)
 rename contrib/hxt/{ => tetMesh/src}/hxt_tetNodalSize.c (96%)
 rename contrib/hxt/{ => tetMesh/src}/hxt_tetNodalSize.h (76%)
 create mode 100644 contrib/hxt/tetMesh/src/hxt_tetOpti.c
 rename contrib/hxt/{ => tetMesh/src}/hxt_tetOpti.h (85%)
 create mode 100644 contrib/hxt/tetMesh/src/hxt_tetOptiUtils.h
 create mode 100644 contrib/hxt/tetMesh/src/hxt_tetPartition.h
 create mode 100644 contrib/hxt/tetMesh/src/hxt_tetQuality.c
 rename contrib/hxt/{ => tetMesh/src}/hxt_tetQuality.h (73%)
 rename contrib/hxt/{ => tetMesh/src}/hxt_tetRefine.c (55%)
 rename contrib/hxt/{ => tetMesh/src}/hxt_tetRefine.h (73%)
 rename contrib/hxt/{ => tetMesh/src}/hxt_tetRepair.c (75%)
 rename contrib/hxt/{ => tetMesh/src}/hxt_tetRepair.h (83%)
 rename contrib/hxt/{ => tetMesh/src}/hxt_tetSync.c (92%)
 rename contrib/hxt/{ => tetMesh/src}/hxt_tetSync.h (87%)
 rename contrib/hxt/{ => tetMesh/src}/hxt_tetUtils.c (88%)
 rename contrib/hxt/{ => tetMesh/src}/hxt_tetUtils.h (86%)
 rename contrib/hxt/{ => tetMesh/src}/hxt_vertices.c (99%)
 rename contrib/hxt/{ => tetMesh/src}/hxt_vertices.h (93%)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index c9320475e6..cfeb4c73ea 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1200,28 +1200,35 @@ if(HAVE_SOLVER)
   endif()
 endif()
 
-if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/contrib/hxt AND
-   ENABLE_HXT AND HAVE_METIS)
-  set_config_option(HAVE_HXT "Hxt")
-  add_subdirectory(contrib/hxt)
-  include_directories(BEFORE contrib/hxt)
-  if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/contrib/hxt/hxt_tetDelaunay.c)
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/contrib/hxt AND ENABLE_HXT)
+  if("${CMAKE_VERSION}" VERSION_LESS "3.9.0")
+    message(WARNING "Your CMake version is not sufficient to compile hxt")
+  else()
+    set_config_option(HAVE_HXT "Hxt")
     set_config_option(HAVE_HXT3D "Hxt3D")
-  endif()
-  if(MSVC)
-    # Visual C++ does not support C99 - force compilation as C++ code
-    file(GLOB_RECURSE HXT_SRC contrib/hxt/*.c)
-    set_compile_flags(HXT_SRC "/TP")
-  endif()
-  check_include_file("immintrin.h" HAVE_IMMINTRIN_H)
-  if(NOT HAVE_IMMINTRIN_H)
-    add_definitions(-DHAVE_NO_IMMINTRIN_H)
-  endif()
-  if(HAVE_PETSC)
-    add_definitions(-DHXT_HAVE_PETSC)
-  endif()
-  if(CMAKE_C_COMPILER MATCHES "pgi")
-    add_definitions(-DHAVE_NO_OPENMP_SIMD)
+
+    set(HXT_REPARAM_OBJECT_ONLY ON CACHE BOOL "use object library" FORCE)
+    set(HXT_TETMESH_OBJECT_ONLY ON CACHE BOOL "use object library" FORCE)
+    set(HXT_TETBR_OBJECT_ONLY ON CACHE BOOL "use object library" FORCE)
+
+    add_subdirectory(contrib/hxt/core) # need to be included before reparam tetMesh & tetBR
+    add_subdirectory(contrib/hxt/predicates) # need to be included before tetMesh & tetBR
+    add_subdirectory(contrib/hxt/reparam)
+    add_subdirectory(contrib/hxt/tetMesh)
+    add_subdirectory(contrib/hxt/tetBR)
+
+    list(APPEND EXTERNAL_LIBRARIES hxt_core hxt_predicates hxt_reparam hxt_tetMesh hxt_tetBR)
+    list(APPEND EXTERNAL_INCLUDES $<TARGET_PROPERTY:hxt_core,INCLUDE_DIRECTORIES>
+                                  $<TARGET_PROPERTY:hxt_predicates,INCLUDE_DIRECTORIES>
+                                  $<TARGET_PROPERTY:hxt_reparam,INCLUDE_DIRECTORIES>
+                                  $<TARGET_PROPERTY:hxt_tetMesh,INCLUDE_DIRECTORIES>
+                                  $<TARGET_PROPERTY:hxt_tetBR,INCLUDE_DIRECTORIES>)
+
+    if(HAVE_P4EST)
+      # this will compile together with GMSH
+      add_subdirectory(contrib/hxt/sizeField)
+      include_directories(BEFORE contrib/hxt/sizeField)
+    endif()
   endif()
 endif()
 
diff --git a/Geo/GModelParametrize.cpp b/Geo/GModelParametrize.cpp
index 5b6ffe0907..3eecfed250 100644
--- a/Geo/GModelParametrize.cpp
+++ b/Geo/GModelParametrize.cpp
@@ -33,6 +33,7 @@
 #if defined(HAVE_HXT)
 extern "C" {
 #include "hxt_mesh.h"
+#include "hxt_tools.h"
 #include "hxt_edge.h"
 #include "hxt_curvature.h"
 #include "hxt_linear_system.h"
@@ -482,10 +483,8 @@ static HXTStatus gmsh2hxt(int tag, const std::vector<MTriangle *> &t,
                           HXTMesh **pm, std::map<MVertex *, int> &v2c,
                           std::vector<MVertex *> &c2v)
 {
-  HXTContext *context;
-  hxtContextCreate(&context);
   HXTMesh *m;
-  HXT_CHECK(hxtMeshCreate(context, &m));
+  HXT_CHECK(hxtMeshCreate(&m));
   std::set<MVertex *> all;
   for(std::size_t i = 0; i < t.size(); i++) {
     all.insert(t[i]->getVertex(0));
diff --git a/Geo/discreteFace.cpp b/Geo/discreteFace.cpp
index 8233cf8374..8e20c4d632 100644
--- a/Geo/discreteFace.cpp
+++ b/Geo/discreteFace.cpp
@@ -20,6 +20,7 @@
 #if defined(HAVE_HXT)
 extern "C" {
 #include "hxt_mesh.h"
+#include "hxt_tools.h"
 #include "hxt_edge.h"
 #include "hxt_mean_values.h"
 #include "hxt_linear_system.h"
@@ -446,10 +447,8 @@ static HXTStatus gmsh2hxt(GFace *gf, HXTMesh **pm,
   int tag = gf->tag();
   const std::vector<MTriangle *> &t = gf->triangles;
 
-  HXTContext *context;
-  hxtContextCreate(&context);
   HXTMesh *m;
-  HXT_CHECK(hxtMeshCreate(context, &m));
+  HXT_CHECK(hxtMeshCreate(&m));
   std::set<MVertex *> all;
   for(size_t i = 0; i < t.size(); i++) {
     all.insert(t[i]->getVertex(0));
diff --git a/Mesh/automaticMeshSizeField.cpp b/Mesh/automaticMeshSizeField.cpp
index 8e6962fcf2..b2d2f5e847 100644
--- a/Mesh/automaticMeshSizeField.cpp
+++ b/Mesh/automaticMeshSizeField.cpp
@@ -5,6 +5,7 @@
 
 #ifdef HAVE_HXT
 extern "C" {
+#include "hxt_tools.h"
 #include "hxt_edge.h"
 #include "hxt_curvature.h"
 #include "hxt_bbox.h"
@@ -66,9 +67,7 @@ HXTStatus automaticMeshSizeField:: updateHXT(){
 
   // create HXT mesh structure
   HXTMesh *mesh;
-  HXTContext *context;
-  HXT_CHECK(hxtContextCreate(&context));
-  HXT_CHECK(hxtMeshCreate(context, &mesh));
+  HXT_CHECK(hxtMeshCreate(&mesh));
   std::map<MVertex *, int> v2c;
   std::vector<MVertex *> c2v;
   Gmsh2Hxt(regions, mesh, v2c, c2v);
diff --git a/Mesh/automaticMeshSizeField.h b/Mesh/automaticMeshSizeField.h
index 915d2f6b1b..aa910f45aa 100644
--- a/Mesh/automaticMeshSizeField.h
+++ b/Mesh/automaticMeshSizeField.h
@@ -3,7 +3,7 @@
 
 #include "GmshConfig.h"
 
-#ifdef HAVE_HXT
+#if defined(HAVE_HXT) && defined(HAVE_P4EST)
 #include "hxt_octree.h"
 #endif
 
diff --git a/Mesh/meshGRegionHxt.cpp b/Mesh/meshGRegionHxt.cpp
index 1634649cb9..47aff61de8 100644
--- a/Mesh/meshGRegionHxt.cpp
+++ b/Mesh/meshGRegionHxt.cpp
@@ -26,7 +26,7 @@
 #if defined(HAVE_HXT3D)
 
 extern "C" {
-#include "hxt_api.h"
+#include "hxt_tools.h"
 #include "hxt_boundary_recovery.h"
 #include "hxt_tetMesh.h"
 }
@@ -365,9 +365,7 @@ static HXTStatus _meshGRegionHxt(std::vector<GRegion *> &regions)
 
   /*******************  ^ all argument were processed *********************/
   HXTMesh *mesh;
-  HXTContext *context;
-  HXT_CHECK(hxtContextCreate(&context));
-  HXT_CHECK(hxtMeshCreate(context, &mesh));
+  HXT_CHECK(hxtMeshCreate(&mesh));
 
   std::map<MVertex *, int> v2c;
   std::vector<MVertex *> c2v;
@@ -399,7 +397,6 @@ static HXTStatus _meshGRegionHxt(std::vector<GRegion *> &regions)
   HXT_CHECK(Hxt2Gmsh(regions, mesh, v2c, c2v));
 
   HXT_CHECK(hxtMeshDelete(&mesh));
-  HXT_CHECK(hxtContextDelete(&context));
   return HXT_STATUS_OK;
 }
 
diff --git a/contrib/hxt/CMakeLists.txt b/contrib/hxt/CMakeLists.txt
deleted file mode 100644
index ee142416e6..0000000000
--- a/contrib/hxt/CMakeLists.txt
+++ /dev/null
@@ -1,65 +0,0 @@
-# Gmsh - Copyright (C) 1997-2020 C. Geuzaine, J.-F. Remacle
-#
-# See the LICENSE.txt file for license information. Please report all
-# issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
-
-# HXT (reparametrization)
-set(SRC
-  hxt_context.c
-  hxt_curvature.c
-  hxt_edge.c
-  hxt_laplace.c
-  hxt_linear_system.c
-  hxt_linear_system_lu.c
-  hxt_linear_system_petsc.c
-  hxt_mean_values.c
-  hxt_mesh.c
-  hxt_message.c
-  hxt_parametrization.c
-  hxt_tools.c
- )
-
-# HXT3D (3D meshing)
-if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/hxt_tetDelaunay.c)
-set(SRC ${SRC}
-  hxt_bbox.c
-  hxt_boundary_recovery.cxx
-  hxt_edgeRemoval.c
-  hxt_mesh.c
-  hxt_smoothing.c
-  hxt_sort.c
-  hxt_tetColor.c
-  hxt_tetDelaunay.c
-  hxt_tetFlag.c
-  hxt_tetMesh.c
-  hxt_tetNodalSize.c
-  hxt_tetOpti.c
-  hxt_tetPostpro.c
-  hxt_tetQuality.c
-  hxt_tetRefine.c
-  hxt_tetRepair.c
-  hxt_tetSync.c
-  hxt_tetUtils.c
-  hxt_vertices.c
-  hxt_octree.cpp
-  HXTSPR.c
-  predicates.c
-)
-endif()
-
-# do not use arithmetic contraction in predicates.c
-if("x${CMAKE_C_COMPILER_ID}" STREQUAL "xMSVC" )
-  set_source_files_properties(predicates.c PROPERTIES COMPILE_FLAGS
-                              "/fp:strict")
-endif()
-if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang")
-  set_source_files_properties(predicates.c PROPERTIES COMPILE_FLAGS
-                              "-fno-unsafe-math-optimizations -ffp-contract=off")
-endif()
-if(CMAKE_C_COMPILER_ID STREQUAL "Intel")
- set_source_files_properties(predicates.c PROPERTIES COMPILE_FLAGS
-                             "-fp-model strict")
-endif()
-
-file(GLOB_RECURSE HDR RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.h)
-append_gmsh_src(contrib/hxt "${SRC};${HDR}")
diff --git a/contrib/hxt/CREDITS.txt b/contrib/hxt/CREDITS.txt
index 5a7b1896f2..b837763c3a 100644
--- a/contrib/hxt/CREDITS.txt
+++ b/contrib/hxt/CREDITS.txt
@@ -2,8 +2,8 @@
 
                Universite catholique de Louvain
 
-The TetGen/BR code (tetgenBR.{cxx,h}) is copyright (c) 2016 Hang Si,
-Weierstrass Institute for Applied Analysis and Stochatics. It is relicensed
-under the terms of gmsh/LICENSE.txt for use in Gmsh thanks to a Software License
-Agreement between Weierstrass Institute for Applied Analysis and Stochastics and
-GMESH SPRL.
+The TetGen/BR code (hxt_boundaryRecovery/src/tetgenBR.{cxx,h}) is copyright (c)
+2016 Hang Si, Weierstrass Institute for Applied Analysis and Stochatics. It is
+relicensed under the terms of gmsh/LICENSE.txt for use in Gmsh thanks to a
+Software License Agreement between Weierstrass Institute for Applied Analysis
+and Stochastics and GMESH SPRL.
diff --git a/contrib/hxt/core/CMakeLists.txt b/contrib/hxt/core/CMakeLists.txt
new file mode 100644
index 0000000000..d88337ed53
--- /dev/null
+++ b/contrib/hxt/core/CMakeLists.txt
@@ -0,0 +1,50 @@
+cmake_minimum_required(VERSION 3.9)
+project(hxt_core C)
+
+if(TARGET hxt_core)
+  # header guard for CMake. You need to include this directory first
+  return()
+endif()
+
+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)
+
+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_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_sort.h"
+    "${CMAKE_CURRENT_SOURCE_DIR}/include/hxt_tools.h"
+   )
+
+if(HXT_CORE_OBJECT_ONLY)
+  # make an object library (no archive)
+  add_library(hxt_core OBJECT ${HXT_CORE_SRC})
+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)
+
+if(HXT_ENABLE_OPENMP)
+  find_package(OpenMP 4)
+  if(OpenMP_C_FOUND)
+      target_link_libraries(hxt_core PUBLIC OpenMP::OpenMP_C)
+  endif()
+endif()
+
+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/hxt_bbox.h b/contrib/hxt/core/include/hxt_bbox.h
similarity index 90%
rename from contrib/hxt/hxt_bbox.h
rename to contrib/hxt/core/include/hxt_bbox.h
index f96f5d82f8..ca37248a3f 100644
--- a/contrib/hxt/hxt_bbox.h
+++ b/contrib/hxt/core/include/hxt_bbox.h
@@ -1,13 +1,21 @@
-#ifndef _HXT_BBOX_H_
-#define _HXT_BBOX_H_
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
 
-#include <hxt_tools.h> // for stdint.h and hxtDeclareAligned32 only
-#include <float.h>
+#ifndef HXT_BBOX_H
+#define HXT_BBOX_H
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#include <hxt_tools.h> // for stdint.h and hxtDeclareAligned32 only
+#include <float.h>
+
 // the fourth member is unused...
 typedef struct hxtBboxStruct{
   double hxtDeclareAligned32 min[3];
diff --git a/contrib/hxt/hxt_mesh.h b/contrib/hxt/core/include/hxt_mesh.h
similarity index 79%
rename from contrib/hxt/hxt_mesh.h
rename to contrib/hxt/core/include/hxt_mesh.h
index cc1d5ba0cb..46134e3274 100644
--- a/contrib/hxt/hxt_mesh.h
+++ b/contrib/hxt/core/include/hxt_mesh.h
@@ -1,12 +1,13 @@
-#ifndef _HEXTREME_MESH_
-#define _HEXTREME_MESH_
+#ifndef HXT_MESH_H
+#define HXT_MESH_H
 
-#include "hxt_tools.h" // to have SIMD_ALIGN and stdint.h
-
-#if defined(WIN32) && !defined(INT32_MAX) // FIXME: Gmsh
-#define INT32_MAX        2147483647i32
+#ifdef __cplusplus
+extern "C" {
 #endif
 
+#include "hxt_message.h"
+#include <stdint.h>
+
 #define HXT_GHOST_VERTEX UINT32_MAX
 
 #define HXT_NO_ADJACENT UINT64_MAX
@@ -23,9 +24,7 @@ typedef enum {
   HXT_PYR = 7
 } HXT_ELT_TYPE;
 
-struct hxtMeshStruct {
-  HXTContext* ctx;
-
+typedef struct {
   // vertices
   struct {
     uint32_t num;
@@ -43,7 +42,7 @@ struct hxtMeshStruct {
     uint64_t num;    // number of tetrahedra
     uint64_t size;   // reserved number of tetrahedra (size of the vector)
   } tetrahedra;
-
+  
   // hexahedra
   struct {
     uint32_t* node;  // aligned (size = hexahedra.size*8*sizeof(uint32_t))
@@ -65,7 +64,7 @@ struct hxtMeshStruct {
     uint64_t num;    // number of tetrahedra
     uint64_t size;   // reserved number of prisms (size of the vector)
   } prisms;
-
+  
   // pyramids
   struct {
     uint32_t* node;  // aligned (size = pyramids.size*5*sizeof(uint32_t))
@@ -80,12 +79,20 @@ struct hxtMeshStruct {
   // triangles // TODO: consider writing a array of structure...
   struct {
     uint32_t* node;
-    uint64_t* neigh;
+    uint64_t* neigh; 
     uint16_t* colors;
     uint64_t num;
     uint64_t size;
   } triangles;
 
+  struct {
+    uint32_t* node;
+    uint64_t* neigh; 
+    uint16_t* colors;
+    uint64_t num;
+    uint64_t size;
+  } triangles2;
+
   // quads
   struct {
     uint32_t* node;
@@ -102,6 +109,13 @@ struct hxtMeshStruct {
     uint64_t size;
   } lines;
 
+  struct {
+    uint32_t* node;
+    uint16_t* colors;
+    uint32_t num;
+    uint32_t size;
+  } points;
+
   // boundary representation
   struct {
     uint16_t numVolumes;
@@ -115,7 +129,18 @@ struct hxtMeshStruct {
     uint16_t numPoints;
     uint16_t *points;
   } brep;
-};
+} HXTMesh;
+
+HXTStatus  hxtMeshCreate          ( HXTMesh** mesh);
+HXTStatus  hxtMeshDelete          ( HXTMesh** meshPtr);
 
+#ifdef HXT_CORE_FILEIO
+HXTStatus  hxtMeshReadGmsh       ( HXTMesh* mesh, const char* filename);
+HXTStatus  hxtMeshWriteGmsh      ( HXTMesh* mesh, const char* filename);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
 
 #endif
diff --git a/contrib/hxt/hxt_message.h b/contrib/hxt/core/include/hxt_message.h
similarity index 53%
rename from contrib/hxt/hxt_message.h
rename to contrib/hxt/core/include/hxt_message.h
index e1b4ff2bb3..0ca3f52240 100644
--- a/contrib/hxt/hxt_message.h
+++ b/contrib/hxt/core/include/hxt_message.h
@@ -1,8 +1,60 @@
-#ifndef _MESSAGE_H_
-#define _MESSAGE_H_
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
+#ifndef HXT_MESSAGE_H
+#define HXT_MESSAGE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdarg.h>
+
+
+/* HEXTREME FUNCTIONS ONLY RETURN A STATUS (except hxtGetMessageString)*/
+typedef enum
+{
+  // positive values mean a success         => HXT_CHECK does nothing for positive values
+  HXT_STATUS_OK                    = 0,
+  HXT_STATUS_TRUE                  = 0,
+  HXT_STATUS_FALSE                 = 1,
+
+
+  // ====== ERRORS
+  // negatives values means errors
+
+  // Fatal Errors                            => HXT_CHECK give trace message and return
+  HXT_STATUS_ERROR                 = -1,
+  HXT_STATUS_FAILED                = -2,
+  HXT_STATUS_ASSERTION_FAILED      = -3,
+  HXT_STATUS_OUT_OF_MEMORY         = -4,
+  HXT_STATUS_FILE_CANNOT_BE_OPENED = -5,
+  HXT_STATUS_POINTER_ERROR         = -6,
+  HXT_STATUS_READ_ERROR            = -7,
+  HXT_STATUS_WRITE_ERROR           = -8,
+  HXT_STATUS_RANGE_ERROR           = -9,
+  HXT_STATUS_FORMAT_ERROR          = -10,
+
+
+  // INTERNAL Errors (<= HXT_STATUS_INTERNAL) => HXT_CHECK does not give trace message but returns... should be catched internally !
+  HXT_STATUS_INTERNAL              = -1024,
+  HXT_STATUS_SKIP                  = -1025,
+  HXT_STATUS_TRYAGAIN              = -1026,
+  // a smoothing or topological operation can silently fail because of these
+  HXT_STATUS_CONFLICT              = -1027,
+  HXT_STATUS_CONSTRAINT            = -1028,
+  HXT_STATUS_NOTBETTER             = -1029,
+  HXT_STATUS_DOUBLE_PT             = -1030
+
+
+}HXTStatus;
 
-#include "hxt_api.h"
-#include "hxt_omp.h"
 
 #define STR(x) #x
 #define STRINGIFY(x) STR(x)
@@ -50,9 +102,33 @@
 #endif
 
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+const char*  hxtGetStatusString(HXTStatus status);
+
+
+/* MESSAGE */
+typedef struct {
+  /* the message content */
+  const char* string; // lifetime = time of callback function
+
+  /* information about the location of the code which sent the message */
+  const char* func;   // lifetime = forever
+  const char* file;   // lifetime = forever
+  const char* line;   // lifetime = forever
+  int threadId;      // the thread which sent the message
+  int numThreads;    // the number of threads
+
+  enum{
+    HXT_MSGLEVEL_INFO     = 0,
+    HXT_MSGLEVEL_DEBUG    = 1,
+    HXT_MSGLEVEL_WARNING  = 2,
+    HXT_MSGLEVEL_ERROR    = 3,
+    HXT_MSGLEVEL_TRACE    = 4
+  } level;
+} HXTMessage;
+
+
+/* MESSAGE AND ERROR HANDLING */
+HXTStatus  hxtSetMessageCallback (HXTStatus (*hxtMsgCallback)(HXTMessage* msg));
 
 HXTStatus  hxtMessageInfo       ( const char* func, const char* file, const char* line, const char *fmt, ...);
 HXTStatus  hxtMessageWarning    ( const char* func, const char* file, const char* line, const char *fmt, ...);
diff --git a/contrib/hxt/hxt_omp.h b/contrib/hxt/core/include/hxt_omp.h
similarity index 100%
rename from contrib/hxt/hxt_omp.h
rename to contrib/hxt/core/include/hxt_omp.h
diff --git a/contrib/hxt/hxt_sort.h b/contrib/hxt/core/include/hxt_sort.h
similarity index 97%
rename from contrib/hxt/hxt_sort.h
rename to contrib/hxt/core/include/hxt_sort.h
index c42be6961f..e6525d0554 100644
--- a/contrib/hxt/hxt_sort.h
+++ b/contrib/hxt/core/include/hxt_sort.h
@@ -1,31 +1,21 @@
-/*  This file is part of HXTSort.                                            *
-                                                                            *
-    HXTSort is free software: you can redistribute it and/or modify         *
-    it under the terms of the GNU General Public License as published by    *
-    the Free Software Foundation, either version 3 of the License, or       *
-    (at your option) any later version.                                     *
-                                                                            *
-    HXTSort is distributed in the hope that it will be useful,              *
-    but WITHOUT ANY WARRANTY; without even the implied warranty of          *
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
-    GNU General Public License for more details.                            *
-                                                                            *
-    You should have received a copy of the GNU General Public License       *
-    along with HXTSort.  If not, see <http://www.gnu.org/licenses/>.        *
-                                                                            *
-    See the COPYING file for the GNU General Public License .               *
-                                                                            *
-Author: Célestin Marot (celestin.marot@uclouvain.be)                        */
-
-#ifndef __HXT_SORT_H__
-#define __HXT_SORT_H__
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
 
-#include "hxt_tools.h"
+#ifndef HXT_SORT_H
+#define HXT_SORT_H
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#include "hxt_tools.h"
+#include "hxt_omp.h"
+
 // sorting function already defined
 typedef struct{
   uint64_t v[2];
@@ -169,6 +159,27 @@ do {                                                                          \
   }                                                                           \
 } while(0)
 
+/* simply sort 4 values */
+#define HXTSORT_4_VALUES_INPLACE(HXTSORT_TYPE, a)                             \
+do {                                                                          \
+  HXTSORT_TYPE* _copya = (a);                                                 \
+  if(_copya[0]>_copya[1]){                                                    \
+    HXTSORT_TYPE _tmp = _copya[0]; _copya[0] = _copya[1]; _copya[1] = _tmp;   \
+  }                                                                           \
+  if(_copya[2]>_copya[3]){                                                    \
+    HXTSORT_TYPE _tmp = _copya[2]; _copya[2] = _copya[3]; _copya[3] = _tmp;   \
+  }                                                                           \
+  if(_copya[0]>_copya[2]){                                                    \
+    HXTSORT_TYPE _tmp = _copya[0]; _copya[0] = _copya[2]; _copya[2] = _tmp;   \
+  }                                                                           \
+  if(_copya[1]>_copya[3]){                                                    \
+    HXTSORT_TYPE _tmp = _copya[1]; _copya[1] = _copya[3]; _copya[3] = _tmp;   \
+  }                                                                           \
+  if(_copya[1]>_copya[2]){                                                    \
+    HXTSORT_TYPE _tmp = _copya[1]; _copya[1] = _copya[2]; _copya[2] = _tmp;   \
+  }                                                                           \
+} while(0)
+
 
 /**************************************************************************************
  * To use pragma in a macro      *
diff --git a/contrib/hxt/hxt_tools.h b/contrib/hxt/core/include/hxt_tools.h
similarity index 81%
rename from contrib/hxt/hxt_tools.h
rename to contrib/hxt/core/include/hxt_tools.h
index 1e6a76e4a3..cefd41eda8 100644
--- a/contrib/hxt/hxt_tools.h
+++ b/contrib/hxt/core/include/hxt_tools.h
@@ -1,3 +1,11 @@
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
 #ifndef HXT_TOOLS_H
 #define HXT_TOOLS_H
 
@@ -5,6 +13,10 @@
 extern "C" {
 #endif
 
+#include "hxt_message.h"
+#include <string.h>
+#include <stdint.h>
+
 /* define SIMD ALIGNMENT */
 #ifndef SIMD_ALIGN
 #ifdef HXT_ALIGN_ALLOCATIONS
@@ -23,8 +35,8 @@ extern "C" {
 #ifndef __restrict__
 #define __restrict__ __restrict
 #endif
-#define HXTu64 "%I64u"
-#define HXTd64 "%I64d"
+#define HXTu64 "I64u"
+#define HXTd64 "I64d"
 #define HXT_LIKELY(exp)   exp
 #define HXT_UNLIKELY(exp) exp
 #define HXT_ASSUME(exp) __assume(exp)
@@ -34,8 +46,8 @@ extern "C" {
 #define hxtDeclareAligned   __attribute__((aligned(SIMD_ALIGN)))
 #define hxtDeclareAligned32 __attribute__((aligned(32)))
 #define hxtDeclareAligned64 __attribute__((aligned(64)))
-#define HXTu64 "%" PRIu64
-#define HXTi64 "%" PRId64
+#define HXTu64 PRIu64
+#define HXTi64 PRId64
 #define HXT_LIKELY(exp)    __builtin_expect(!!(exp), 1)
 #define HXT_UNLIKELY(exp)  __builtin_expect(!!(exp), 0)
 #ifdef __GNUC__
@@ -52,12 +64,6 @@ extern "C" {
 
 #define HXT_UNUSED(x) (void)(x)  // portable way to avoid warning about unused variable
 
-#include <stdio.h>
-#include <string.h>
-#include <stddef.h>
-#include <math.h>
-#include "hxt_message.h" // already include hxt_api (for HXT_status_t and stdint.h)
-
 /*********************************************************
  * Hextreme malloc implementation
  *********************************************************/
@@ -246,34 +252,6 @@ static inline uint32_t hxtReproducibleLCG(uint32_t *seed)
   return *seed;
 }
 
-/*********************************************************
- * Operations on 3D vectors
- *********************************************************/
-HXTStatus hxtNorm2V3(double v[3], double* norm2);
-HXTStatus hxtNorm2V(double v[3], int size, double* norm2);
-HXTStatus hxtNormalizeV3(double v[3]);
-HXTStatus hxtNormalizeV(double *v, int size);
-HXTStatus hxtCrossProductV3(double a[3], double b[3], double res[3]);
-
-/*********************************************************
- * Matrix operations
- *********************************************************/
-HXTStatus hxtDet2x2(double mat[2][2], double* det);
-HXTStatus hxtInv2x2(double mat[2][2], double inv[2][2], double *det);
-HXTStatus hxtDet3x3(double mat[3][3], double *det);
-HXTStatus hxtInv3x3(double mat[3][3], double inv[3][3], double *det);
-
-HXTStatus hxtInv4x4ColumnMajor(double mat[16], double inv[16], double *det);
-
-/*********************************************************
- * Operations on linear Tet
- *********************************************************/
-HXTStatus hxtJacobianLinTet(double *x , double *y, double *z , double mat[3][3]);
-
-#ifndef M_PI
-  #define M_PI 3.14159265358979323846264338327950
-#endif // !M_PI
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/contrib/hxt/hxt_bbox.c b/contrib/hxt/core/src/hxt_bbox.c
similarity index 92%
rename from contrib/hxt/hxt_bbox.c
rename to contrib/hxt/core/src/hxt_bbox.c
index 9bd247b5af..694f23dfa2 100644
--- a/contrib/hxt/hxt_bbox.c
+++ b/contrib/hxt/core/src/hxt_bbox.c
@@ -1,3 +1,11 @@
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
 #include "hxt_bbox.h"
 
 /* update the bounding box with an array of n vertices at once (far quicker) */
diff --git a/contrib/hxt/hxt_mesh.c b/contrib/hxt/core/src/hxt_mesh.c
similarity index 82%
rename from contrib/hxt/hxt_mesh.c
rename to contrib/hxt/core/src/hxt_mesh.c
index 7ea65b5bf5..acc2980767 100644
--- a/contrib/hxt/hxt_mesh.c
+++ b/contrib/hxt/core/src/hxt_mesh.c
@@ -1,4 +1,6 @@
 #include "hxt_mesh.h"
+#include "hxt_tools.h"
+#include <stdio.h>
 #include <float.h>
 
 /* Compatible with HXT_ELT_TYPE enum exposed in header */
@@ -10,84 +12,15 @@
 #define HEXID 5
 #define PRIID 6
 #define PYRID 7
+#define TRIID2 9
 
-HXTStatus  hxtMeshCreate ( HXTContext* ctx, HXTMesh** mesh) {
+HXTStatus  hxtMeshCreate ( HXTMesh** mesh) {
   HXT_CHECK( hxtMalloc (mesh, sizeof(HXTMesh)) );
   if (*mesh == NULL)return HXT_ERROR(HXT_STATUS_OUT_OF_MEMORY);
-  (*mesh)->ctx = ctx;
 
-  // vertices
-  (*mesh)->vertices.coord = NULL;
-  (*mesh)->vertices.num = 0;
-  (*mesh)->vertices.size = 0;
-
-  // tetrahedra
-  (*mesh)->tetrahedra.node = NULL;
-  (*mesh)->tetrahedra.colors = NULL;
-  (*mesh)->tetrahedra.flag = NULL;
-  (*mesh)->tetrahedra.neigh = NULL;
-  (*mesh)->tetrahedra.neighType = NULL;
-  // (*mesh)->tetrahedra.subdet = NULL;
-  (*mesh)->tetrahedra.num = 0;
-  (*mesh)->tetrahedra.size = 0;
-
-  // hexahedra
-  (*mesh)->hexahedra.node = NULL;
-  (*mesh)->hexahedra.colors = NULL;
-  (*mesh)->hexahedra.flag = NULL;
-  (*mesh)->hexahedra.neigh = NULL;
-  (*mesh)->hexahedra.neighType = NULL;
-  (*mesh)->hexahedra.num = 0;
-  (*mesh)->hexahedra.size = 0;
-
-  // prisms
-  (*mesh)->prisms.node = NULL;
-  (*mesh)->prisms.colors = NULL;
-  (*mesh)->prisms.flag = NULL;
-  (*mesh)->prisms.neigh = NULL;
-  (*mesh)->prisms.neighType = NULL;
-  (*mesh)->prisms.num = 0;
-  (*mesh)->prisms.size = 0;
-
-  // pyramids
-  (*mesh)->pyramids.node = NULL;
-  (*mesh)->pyramids.colors = NULL;
-  (*mesh)->pyramids.flag = NULL;
-  (*mesh)->pyramids.neigh = NULL;
-  (*mesh)->pyramids.neighType = NULL;
-  (*mesh)->pyramids.num = 0;
-  (*mesh)->pyramids.size = 0;
-
-  // triangles
-  (*mesh)->triangles.node = NULL;
-  (*mesh)->triangles.neigh = NULL;
-  (*mesh)->triangles.colors = NULL;
-  (*mesh)->triangles.num = 0;
-  (*mesh)->triangles.size = 0;
-
-  // quads
-  (*mesh)->quads.node = NULL;
-  (*mesh)->quads.colors = NULL;
-  (*mesh)->quads.num = 0;
-  (*mesh)->quads.size = 0;
-
-  // lines
-  (*mesh)->lines.node = NULL;
-  (*mesh)->lines.colors = NULL;
-  (*mesh)->lines.num = 0;
-  (*mesh)->lines.size = 0;
-
-  // boundary representation
-  (*mesh)->brep.numVolumes = 0;
-  (*mesh)->brep.numSurfacesPerVolume = NULL;
-  (*mesh)->brep.surfacesPerVolume = NULL;
-  (*mesh)->brep.numSurfaces = 0;
-  (*mesh)->brep.numCurvesPerSurface = NULL;
-  (*mesh)->brep.curvesPerSurface = NULL;
-  (*mesh)->brep.numCurves = 0;
-  (*mesh)->brep.endPointsOfCurves = NULL;
-  (*mesh)->brep.numPoints = 0;
-  (*mesh)->brep.points = NULL;
+  // This line, using a compound literal, will initialize everything
+  // to zero (and pointers to NULL)
+  **mesh = (HXTMesh) {0};
 
   return HXT_STATUS_OK;
 }
@@ -131,6 +64,10 @@ HXTStatus hxtMeshDelete ( HXTMesh** mesh) {
   HXT_CHECK( hxtAlignedFree(&(*mesh)->triangles.node) );
   HXT_CHECK( hxtAlignedFree(&(*mesh)->triangles.colors) );
 
+  // triangles2
+  HXT_CHECK( hxtAlignedFree(&(*mesh)->triangles2.node) );
+  HXT_CHECK( hxtAlignedFree(&(*mesh)->triangles2.colors) );
+
   // quads
   HXT_CHECK( hxtAlignedFree(&(*mesh)->quads.node) );
   HXT_CHECK( hxtAlignedFree(&(*mesh)->quads.colors) );
@@ -139,6 +76,10 @@ HXTStatus hxtMeshDelete ( HXTMesh** mesh) {
   HXT_CHECK( hxtAlignedFree(&(*mesh)->lines.node) );
   HXT_CHECK( hxtAlignedFree(&(*mesh)->lines.colors) );
 
+  // points
+  HXT_CHECK( hxtAlignedFree(&(*mesh)->points.node) );
+
+
   // boundary representation
   HXT_CHECK( hxtAlignedFree(&(*mesh)->brep.numSurfacesPerVolume) );
   HXT_CHECK( hxtAlignedFree(&(*mesh)->brep.surfacesPerVolume) );
@@ -147,11 +88,21 @@ HXTStatus hxtMeshDelete ( HXTMesh** mesh) {
   HXT_CHECK( hxtAlignedFree(&(*mesh)->brep.endPointsOfCurves) );
   HXT_CHECK( hxtAlignedFree(&(*mesh)->brep.points) );
 
+  // reset every fields to zero
+  **mesh = (HXTMesh) {0};
 
   HXT_CHECK( hxtFree(mesh) );
   return HXT_STATUS_OK;
 }
 
+
+
+
+
+
+
+#ifdef HXT_CORE_FILEIO
+
 // TODO: more checking of fgets
 HXTStatus ReadNodesFromGmsh(FILE *fp,  HXTMesh* m){
   rewind (fp);
@@ -184,7 +135,7 @@ HXTStatus ReadNodesFromGmsh(FILE *fp,  HXTMesh* m){
 // TODO: add possibility to read the elements from an array
 
 // TODO: more checking of fgets
-// TODO: compute other stuffs, like the subdets...
+// TODO: why set to zero AND use malloc ? => either set to zero and use realloc, either trust it is zero and malloc
 HXTStatus ReadElementsFromGmsh(FILE *fp, HXTMesh* m){
   int k;
   char buf[BUFSIZ]={""};
@@ -192,7 +143,9 @@ HXTStatus ReadElementsFromGmsh(FILE *fp, HXTMesh* m){
   rewind (fp);
 
   m->lines.num = 0;
+  m->points.num = 0;
   m->triangles.num = 0;
+  m->triangles2.num = 0;
   m->quads.num = 0;
   m->tetrahedra.num = 0;
   m->hexahedra.num = 0;
@@ -224,6 +177,9 @@ HXTStatus ReadElementsFromGmsh(FILE *fp, HXTMesh* m){
         else if(etype==TRIID){ // triangles
           ++(m->triangles.num);
         }
+        else if(etype==TRIID2){ // triangles p2
+          ++(m->triangles2.num);
+        }
         else if(etype==QUADID){ // quads
           ++(m->quads.num);
         }
@@ -232,6 +188,7 @@ HXTStatus ReadElementsFromGmsh(FILE *fp, HXTMesh* m){
         }
         else if(etype==POINTID){ // points
           //          ++(m->lines.num);
+          ++(m->points.num);
         }
       }      
       break;
@@ -277,6 +234,13 @@ HXTStatus ReadElementsFromGmsh(FILE *fp, HXTMesh* m){
     if (m->triangles.colors == NULL)return HXT_ERROR(HXT_STATUS_OUT_OF_MEMORY);
     m->triangles.size = m->triangles.num;
   }
+  if (m->triangles2.num){
+    HXT_CHECK( hxtAlignedMalloc(&m->triangles2.node, (m->triangles2.num)*6*sizeof(uint32_t)) );
+    if (m->triangles2.node == NULL)return HXT_ERROR(HXT_STATUS_OUT_OF_MEMORY);
+    HXT_CHECK( hxtAlignedMalloc(&m->triangles2.colors, (m->triangles2.num)*sizeof(uint16_t)) );
+    if (m->triangles2.colors == NULL)return HXT_ERROR(HXT_STATUS_OUT_OF_MEMORY);
+    m->triangles2.size = m->triangles2.num;
+  }
   if (m->quads.num){
     HXT_CHECK( hxtAlignedMalloc(&m->quads.node, (m->quads.num)*4*sizeof(uint32_t)) );
     if (m->quads.node == NULL)return HXT_ERROR(HXT_STATUS_OUT_OF_MEMORY);
@@ -291,6 +255,11 @@ HXTStatus ReadElementsFromGmsh(FILE *fp, HXTMesh* m){
     if (m->lines.colors == NULL)return HXT_ERROR(HXT_STATUS_OUT_OF_MEMORY);
     m->lines.size = m->lines.num;
   }
+  if (m->points.num){
+    HXT_CHECK( hxtAlignedMalloc(&m->points.node, (m->points.num)*sizeof(uint32_t)) );
+    if (m->points.node == NULL)return HXT_ERROR(HXT_STATUS_OUT_OF_MEMORY);
+    m->points.size = m->points.num;
+  }
         
   while( fgets(buf, BUFSIZ, fp )){
 
@@ -304,8 +273,10 @@ HXTStatus ReadElementsFromGmsh(FILE *fp, HXTMesh* m){
       m->prisms.num=0;
       m->pyramids.num=0;
       m->triangles.num=0;
+      m->triangles2.num=0;
       m->quads.num=0;
       m->lines.num=0;
+      m->points.num=0;
       
       for(k=0;k<tmpK;++k){
         int etype = 0, ntags;
@@ -383,6 +354,21 @@ HXTStatus ReadElementsFromGmsh(FILE *fp, HXTMesh* m){
           }
           ++m->triangles.num;
         }
+        else if(etype==TRIID2){ // triangles
+          if(ntags==2){ // 
+            int a, b, c, d, e, f, color;
+            sscanf(buf, "%*d %*d %*d %*d %d   %d %d %d %d %d %d", 
+                   &color,&a, &b, &c, &d, &e, &f);
+            m->triangles2.node[6*m->triangles.num+0] = a-1;
+            m->triangles2.node[6*m->triangles.num+1] = b-1;
+            m->triangles2.node[6*m->triangles.num+2] = c-1;
+            m->triangles2.node[6*m->triangles.num+3] = d-1;
+            m->triangles2.node[6*m->triangles.num+4] = e-1;
+            m->triangles2.node[6*m->triangles.num+5] = f-1;
+            m->triangles2.colors[m->triangles.num] = color;
+          }
+          ++m->triangles2.num;
+        }
         else if(etype==QUADID){ // quads
           if(ntags==2){ // 
             int a, b, c, d, color;
@@ -400,9 +386,11 @@ HXTStatus ReadElementsFromGmsh(FILE *fp, HXTMesh* m){
           if(ntags==2){ // 
             int a;
             sscanf(buf, "%*d %*d %*d %*d %*d  %d",&a);
+            m->points.node[m->points.num] = a-1;
             //            m->lines.node[2*m->lines.num+0] = a-1;
             //            m->lines.node[2*m->lines.num+1] = b-1;
           }
+          ++m->points.num;
         }
         if(etype==LINEID){ // lines
           if(ntags==2){ // 
@@ -470,17 +458,19 @@ HXTStatus  hxtMeshWriteGmsh  ( HXTMesh* mesh , const char *filename) {
     if(mesh->tetrahedra.node[i*4 + 3]!=UINT32_MAX){
       uint16_t myColor = mesh->tetrahedra.colors ? mesh->tetrahedra.colors[i] : 0;
       // color = UINT16_MAX --> outside the domain
-      //      if (myColor != UINT16_MAX)
+      if (myColor != UINT16_MAX)
         ++index;
     }
   }
   
   fprintf(file,"$EndNodes\n"
           "$Elements\n"
-          "%lu\n",
+          "%" HXTu64 "\n",
           index
+          + mesh->points.num
           + mesh->lines.num
           + mesh->triangles.num
+          + mesh->triangles2.num
           + mesh->quads.num
           + mesh->hexahedra.num
           + mesh->prisms.num
@@ -490,24 +480,40 @@ HXTStatus  hxtMeshWriteGmsh  ( HXTMesh* mesh , const char *filename) {
   { /* print the elements */
     
     index = 0;
+    for (i=0; i<mesh->points.num; i++){
+      fprintf(file,"%lu %u 2 0 %u %u\n", ++index,POINTID,
+              mesh->points.node[i]+1,
+              mesh->points.node[i]+1);
+    }
     for (i=0; i<mesh->lines.num; i++){
       uint16_t myColor = mesh->lines.colors ? mesh->lines.colors[i] : 0;
-      fprintf(file,"%lu %u 2 0 %u %u %u\n", ++index,LINEID,
+      fprintf(file, "%" HXTu64 " %u 2 0 %u %u %u\n", ++index,LINEID,
               myColor,
               mesh->lines.node[i*2]+1,
               mesh->lines.node[i*2 + 1]+1);
     }
     for (i=0; i<mesh->triangles.num; i++){
       uint16_t myColor = mesh->triangles.colors ? mesh->triangles.colors[i] : 0;
-      fprintf(file,"%lu %u 2 0 %u %u %u %u\n", ++index,TRIID,
+      fprintf(file, "%" HXTu64 " %u 2 0 %u %u %u %u\n", ++index,TRIID,
               myColor,
               mesh->triangles.node[i*3]+1,
               mesh->triangles.node[i*3 + 1]+1,
               mesh->triangles.node[i*3 + 2]+1);
     }
+    for (i=0; i<mesh->triangles2.num; i++){
+      uint16_t myColor = mesh->triangles2.colors ? mesh->triangles2.colors[i] : 0;
+      fprintf(file, "%" HXTu64 " %u 2 0 %u %u %u %u %u %u %u\n", ++index,TRIID2,
+              myColor,
+              mesh->triangles2.node[i*6 + 0]+1,
+              mesh->triangles2.node[i*6 + 1]+1,
+              mesh->triangles2.node[i*6 + 2]+1,
+	      mesh->triangles2.node[i*6 + 3]+1,
+	      mesh->triangles2.node[i*6 + 4]+1,
+	      mesh->triangles2.node[i*6 + 5]+1);
+    }
     for (i=0; i<mesh->quads.num; i++){
       uint16_t myColor = mesh->quads.colors ? mesh->quads.colors[i] : 0;
-      fprintf(file,"%lu %u 2 0 %u %u %u %u %u\n", ++index,QUADID,
+      fprintf(file, "%" HXTu64 " %u 2 0 %u %u %u %u %u\n", ++index,QUADID,
               myColor,
               mesh->quads.node[i*4]+1,
               mesh->quads.node[i*4 + 1]+1,
@@ -518,8 +524,8 @@ HXTStatus  hxtMeshWriteGmsh  ( HXTMesh* mesh , const char *filename) {
     for (i=0; i<mesh->tetrahedra.num; i++){
       if(mesh->tetrahedra.node[i*4 + 3]!=UINT32_MAX){
         uint16_t myColor = mesh->tetrahedra.colors ? mesh->tetrahedra.colors[i] : 0;
-	//        if (myColor != UINT16_MAX)
-          fprintf(file,"%lu %u 2 0 %u %u %u %u %u\n", ++index,TETID,
+        if (myColor != UINT16_MAX)
+          fprintf(file, "%" HXTu64 " %u 2 0 %u %u %u %u %u\n", ++index,TETID,
               myColor,
               mesh->tetrahedra.node[i*4]+1,
               mesh->tetrahedra.node[i*4 + 1]+1,
@@ -531,7 +537,7 @@ HXTStatus  hxtMeshWriteGmsh  ( HXTMesh* mesh , const char *filename) {
       if(mesh->hexahedra.node[i*8 + 7]!=UINT32_MAX){
         uint16_t myColor = mesh->hexahedra.colors ? mesh->hexahedra.colors[i] : 0;
         if (myColor != UINT16_MAX)
-          fprintf(file,"%lu %u 2 0 %u %u %u %u %u %u %u %u %u\n", ++index,HEXID,
+          fprintf(file, "%" HXTu64 " %u 2 0 %u %u %u %u %u %u %u %u %u\n", ++index,HEXID,
               myColor,
               mesh->hexahedra.node[i*8]+1,
               mesh->hexahedra.node[i*8 + 1]+1,
@@ -547,7 +553,7 @@ HXTStatus  hxtMeshWriteGmsh  ( HXTMesh* mesh , const char *filename) {
       if(mesh->prisms.node[i*6 + 5]!=UINT32_MAX){
         uint16_t myColor = mesh->prisms.colors ? mesh->prisms.colors[i] : 0;
         if (myColor != UINT16_MAX)
-          fprintf(file,"%lu %u 2 0 %u %u %u %u %u %u %u\n", ++index,PRIID,
+          fprintf(file, "%" HXTu64 " %u 2 0 %u %u %u %u %u %u %u\n", ++index,PRIID,
               myColor,
               mesh->prisms.node[i*6]+1,
               mesh->prisms.node[i*6 + 1]+1,
@@ -561,7 +567,7 @@ HXTStatus  hxtMeshWriteGmsh  ( HXTMesh* mesh , const char *filename) {
       if(mesh->pyramids.node[i*5 + 4]!=UINT32_MAX){
         uint16_t myColor = mesh->pyramids.colors ? mesh->pyramids.colors[i] : 0;
         if (myColor != UINT16_MAX)
-          fprintf(file,"%lu %u 2 0 %u %u %u %u %u %u\n", ++index,PYRID,
+          fprintf(file, "%" HXTu64 " %u 2 0 %u %u %u %u %u %u\n", ++index,PYRID,
               myColor,
               mesh->pyramids.node[i*5]+1,
               mesh->pyramids.node[i*5 + 1]+1,
@@ -577,4 +583,5 @@ HXTStatus  hxtMeshWriteGmsh  ( HXTMesh* mesh , const char *filename) {
   return HXT_STATUS_OK;
 }
 
+#endif
 
diff --git a/contrib/hxt/hxt_message.c b/contrib/hxt/core/src/hxt_message.c
similarity index 96%
rename from contrib/hxt/hxt_message.c
rename to contrib/hxt/core/src/hxt_message.c
index bedd547d23..46692e04e8 100644
--- a/contrib/hxt/hxt_message.c
+++ b/contrib/hxt/core/src/hxt_message.c
@@ -1,5 +1,14 @@
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
 #include <stdlib.h>
 #include <stdio.h>
+#include "hxt_omp.h"
 #include "hxt_message.h"
 
 
diff --git a/contrib/hxt/hxt_sort.c b/contrib/hxt/core/src/hxt_sort.c
similarity index 93%
rename from contrib/hxt/hxt_sort.c
rename to contrib/hxt/core/src/hxt_sort.c
index 4bece40a22..a45cdac0fe 100644
--- a/contrib/hxt/hxt_sort.c
+++ b/contrib/hxt/core/src/hxt_sort.c
@@ -1,3 +1,11 @@
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
 #include "hxt_sort.h"
 
 
diff --git a/contrib/hxt/hxt_api.h b/contrib/hxt/hxt_api.h
deleted file mode 100644
index d2b876b000..0000000000
--- a/contrib/hxt/hxt_api.h
+++ /dev/null
@@ -1,118 +0,0 @@
-#ifndef _HEXTREME_API_H_
-#define _HEXTREME_API_H_
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdlib.h>
-#include <stdarg.h>
-#include <stdint.h>
-
-/* HEXTREME FUNCTIONS ONLY RETURN A STATUS (except hxtGetMessageString)*/
-typedef enum
-{
-  // positive values mean a success         => HXT_CHECK does nothing for positive values
-  HXT_STATUS_OK                    = 0,
-  HXT_STATUS_TRUE                  = 0,
-  HXT_STATUS_FALSE                 = 1,
-
-
-  // ====== ERRORS
-  // negatives values means errors
-
-  // Fatal Errors                            => HXT_CHECK give trace message and return
-  HXT_STATUS_ERROR                 = -1,
-  HXT_STATUS_FAILED                = -2,
-  HXT_STATUS_ASSERTION_FAILED      = -3,
-  HXT_STATUS_OUT_OF_MEMORY         = -4,
-  HXT_STATUS_FILE_CANNOT_BE_OPENED = -5,
-  HXT_STATUS_POINTER_ERROR         = -6,
-  HXT_STATUS_READ_ERROR            = -7,
-  HXT_STATUS_WRITE_ERROR           = -8,
-  HXT_STATUS_RANGE_ERROR           = -9,
-  HXT_STATUS_FORMAT_ERROR          = -10,
-
-
-  // INTERNAL Errors (<= HXT_STATUS_INTERNAL) => HXT_CHECK does not give trace message but returns... should be catched internally !
-  HXT_STATUS_INTERNAL              = -1024,
-  HXT_STATUS_SKIP                  = -1025,
-  HXT_STATUS_TRYAGAIN              = -1026,
-  // a smoothing or topological operation can silently fail because of these
-  HXT_STATUS_CONFLICT              = -1027,
-  HXT_STATUS_CONSTRAINT            = -1028,
-  HXT_STATUS_NOTBETTER             = -1029,
-  HXT_STATUS_DOUBLE_PT             = -1030
-
-
-}HXTStatus;
-
-typedef uint32_t HXTIndex;
-
-const char*  hxtGetStatusString(HXTStatus status);
-
-
-/* MESSAGE */
-typedef struct {
-  /* the message content */
-  const char* string; // lifetime = time of callback function
-
-  /* information about the location of the code which sent the message */
-  const char* func;   // lifetime = forever
-  const char* file;   // lifetime = forever
-  const char* line;   // lifetime = forever
-  int threadId;      // the thread which sent the message
-  int numThreads;    // the number of threads
-
-  enum{
-    HXT_MSGLEVEL_INFO     = 0,
-    HXT_MSGLEVEL_DEBUG    = 1,
-    HXT_MSGLEVEL_WARNING  = 2,
-    HXT_MSGLEVEL_ERROR    = 3,
-    HXT_MSGLEVEL_TRACE    = 4
-  } level;
-} HXTMessage;
-
-
-/* INITIALIZE STUFF, SETS GLOBAL PARAMETERS THROUGH COMMAND LINE*/
-HXTStatus hxtInit(int argc, char **argv);
-HXTStatus hxtFinalize(void);
-
-
-/* A CONTEXT SIMILAR TO THE CONTEXT OF GMSH (OPTIONS & CO + MESSAGES) */
-typedef struct hxtContextStruct HXTContext;
-HXTStatus  hxtContextCreate               ( HXTContext** ctxtPtr);
-HXTStatus  hxtContextDelete               ( HXTContext** ctxtPtr);
-
-
-/* MESSAGE AND ERROR HANDLING */
-HXTStatus  hxtSetMessageCallback (HXTStatus (*hxtMsgCallback)(HXTMessage* msg));
-
-
-
-/* THE MESH OBJECT */
-typedef struct hxtMeshStruct HXTMesh ;
-HXTStatus  hxtMeshCreate          ( HXTContext* ctxt, HXTMesh** mesh);
-HXTStatus  hxtMeshDelete          ( HXTMesh** meshPtr);
-HXTStatus  hxtMeshReadGmsh       ( HXTMesh* mesh, const char* filename);
-HXTStatus  hxtMeshWriteGmsh      ( HXTMesh* mesh, const char* filename);
-
-/* THE MESH SIZE OBJECT */
-typedef struct  hxtMeshSizeStruct HXTMeshSize;
-typedef HXTStatus (*HXTMeshSizeCallback)(double x[3], void* data, double* s);
-HXTStatus  hxtMeshSizeCreate     ( HXTContext* ctxt, HXTMeshSize** );
-HXTStatus  hxtMeshSizeDelete     ( HXTMeshSize** );
-HXTStatus  hxtMeshSizeCompute    ( HXTMeshSize* meshSize , double min[3], double max[3], HXTMeshSizeCallback cb, void *data);
-HXTStatus  hxtMeshSizeEvaluate   ( HXTMeshSize* meshSize, double x[3], double* v);
-
-
-/* SOME MESHING ROUTINES */
-HXTStatus  hxtMeshTetrahedralize ( HXTMesh* mesh , HXTMeshSize* meshSize);
-HXTStatus  hxtMeshOptimize       ( HXTMesh* mesh , HXTMeshSize* meshSize);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/contrib/hxt/hxt_bissection.c b/contrib/hxt/hxt_bissection.c
deleted file mode 100644
index f6b9c7babf..0000000000
--- a/contrib/hxt/hxt_bissection.c
+++ /dev/null
@@ -1,458 +0,0 @@
-#include "hxt_edge.h"
-#include "hxt_sort.h"
-
-
-
-static HXTStatus hxtDoubleLongestEdge(HXTEdges *e, int tri, double *l)
-{
-  uint32_t *ed = &e->tri2edg[3*tri];
-  *l=0;
-  
-  for(int i=0; i<3; i++){
-    uint64_t *tr= &e->edg2tri[2*ed[i]];
-    
-    if(tr[1]==(uint64_t)-1)
-      continue;
-
-    if(*l<hxtEdgesLength(e,ed[i]))
-      *l=hxtEdgesLength(e,ed[i]);
-  }
-    return HXT_STATUS_OK;
-    
-}
-
-
-static HXTStatus hxtLongestEdge(HXTEdges *edges, int tri,int *ie,int comp)
-{
-  
-  uint32_t *ed = &edges->tri2edg[3*tri];
-  double longest = hxtEdgesLength(edges,comp);
-  *ie=comp;
-  for(int i=0; i<3; i++){
-    uint64_t *tr= &edges->edg2tri[2*ed[i]];
-    
-    if(tr[1]==(uint64_t)-1)
-      continue;
-
-    if(longest<hxtEdgesLength(edges,ed[i])){
-      longest=hxtEdgesLength(edges,ed[i]);
-      *ie = ed[i];
-    }
-  }
-  return HXT_STATUS_OK;
-}
-
-HXTStatus hxtLongestEdgeBisection(HXTEdges *edges,int nrefinements)
-{
-
-  double threshold = 0, counter=0;
-  for(uint32_t ie=0; ie<edges->numEdges; ie++)
-    if(edges->edg2tri[2*ie+1]==(uint64_t)-1){
-      threshold+= hxtEdgesLength(edges,ie);
-      counter++;
-    }
-  if (counter>0)
-    threshold/=counter;
-
-  // longest-edge bisection: boundary edges are not splitted
-  for(int ir=0; ir<nrefinements; ir++){
-    HXTEdges *e = edges;
-    HXTMesh *m = edges->edg2mesh;
-
-
-    
-    uint64_t *flag=NULL;
-    HXT_CHECK(hxtMalloc(&flag,m->triangles.num*sizeof(uint64_t)));
-    for(uint64_t it=0; it<m->triangles.num; it++){
-      double l;
-      HXT_CHECK(hxtDoubleLongestEdge(e,it,&l));
-      if(l>2*threshold)
-        flag[it] = 0;
-      else
-        flag[it] = 1;
-    }
-
-    int maxVert = m->vertices.num;
-    int maxTri = m->triangles.num;
-    int maxEdg = e->numEdges;
-    uint64_t initialNumberOfTriangles = m->triangles.num;
-    for(uint64_t it=0; it<initialNumberOfTriangles; it++){
-      if(flag[it] > 0)
-        continue;
-
-      while(flag[it]==0){
-        int ti = (int) it, tj;
-        int ei,ej;
-        for(int ib=0; ib<3; ib++){
-          if (e->edg2tri[2*e->tri2edg[3*it+ib]+1] == (uint64_t) -1)
-            continue;
-          else{
-            hxtLongestEdge(e,it,&ej,e->tri2edg[3*it+ib]);
-            break;
-          }
-        }
-        do{       
-          HXT_CHECK(hxtLongestEdge(e,ti,&ei,ej));
-          tj = e->edg2tri[2*ei+0]==ti ? e->edg2tri[2*ei+1] : e->edg2tri[2*ei+0];
-          HXT_CHECK(hxtLongestEdge(e,tj,&ej,ei));
-          ti =  e->edg2tri[2*ej+0]==tj ? e->edg2tri[2*ej+1] : e->edg2tri[2*ej+0];
-        }while(ei!=ej);
-
-        m->vertices.num += 1;
-        if(m->vertices.num > maxVert){
-          maxVert *= 2;
-          HXT_CHECK(hxtAlignedRealloc(&m->vertices.coord,4*maxVert*sizeof(double)));
-        }
-        int ni = e->node[2*ei+0], nj = e->node[2*ei+1];
-
-        for(int xj=0; xj<3; xj++)
-          m->vertices.coord[4*(m->vertices.num-1)+xj] = ( m->vertices.coord[4*ni+xj] + m->vertices.coord[4*nj+xj] )/2.;
-
-        m->triangles.num +=2;
-        if(m->triangles.num > maxTri){
-          maxTri *= 2;
-          HXT_CHECK(hxtAlignedRealloc(&m->triangles.node,3*maxTri*sizeof(uint32_t)));
-          HXT_CHECK(hxtAlignedRealloc(&m->triangles.colors,maxTri*sizeof(uint16_t)));
-          HXT_CHECK(hxtRealloc(&e->tri2edg,3*maxTri*sizeof(uint32_t)));
-        }
-        int tti = m->triangles.num-2, ttj = tti+1;
-        int e0 = e->numEdges, e1=e0+1, e2=e1+1;
-        for(int ic=0; ic<3; ic++){
-          if(m->triangles.node[3*ti+ic]==ni && m->triangles.node[3*ti+(ic+1)%3]==nj){
-            m->triangles.node[3*ti+(ic+1)%3] = m->vertices.num-1;
-
-            m->triangles.node[3*tti+0] = m->vertices.num-1;
-            m->triangles.node[3*tti+1] = nj;
-            m->triangles.node[3*tti+2] = m->triangles.node[3*ti+(ic+2)%3];
-            e->tri2edg[3*tti+0] = e0;
-            e->tri2edg[3*tti+1] = e->tri2edg[3*ti+(ic+1)%3];
-            e->tri2edg[3*tti+2] = e1;
-
-            e->tri2edg[3*ti+(ic+1)%3] = e1;
-
-            uint64_t *t_ = &e->edg2tri[2*e->tri2edg[3*tti+1]];
-            if(t_[0]==ti)
-              t_[0] = tti;
-            else
-              t_[1] = tti;
-
-          }
-          else if (m->triangles.node[3*ti+ic]==nj && m->triangles.node[3*ti+(ic+1)%3]==ni) {
-            m->triangles.node[3*ti+ic] = m->vertices.num-1;
-
-            m->triangles.node[3*tti+0] = nj;
-            m->triangles.node[3*tti+1] = m->vertices.num-1;
-            m->triangles.node[3*tti+2] = m->triangles.node[3*ti+(ic+2)%3];
-            e->tri2edg[3*tti+0] = e0;
-            e->tri2edg[3*tti+1] = e1;
-            e->tri2edg[3*tti+2] = e->tri2edg[3*ti+(ic+2)%3];
-
-            e->tri2edg[3*ti+(ic+2)%3] = e1;
-
-
-            uint64_t *t_ = &e->edg2tri[2*e->tri2edg[3*tti+2]];
-            if(t_[0]==ti)
-              t_[0] = tti;
-            else
-              t_[1] = tti;
-
-          }
-          if(m->triangles.node[3*tj+ic]==nj && m->triangles.node[3*tj+(ic+1)%3]==ni){
-            m->triangles.node[3*tj+(ic+1)%3] = m->vertices.num-1;
-
-            m->triangles.node[3*ttj+0] = m->vertices.num-1;
-            m->triangles.node[3*ttj+1] = ni;
-            m->triangles.node[3*ttj+2] = m->triangles.node[3*tj+(ic+2)%3];
-            e->tri2edg[3*ttj+0] = ei;
-            e->tri2edg[3*ttj+1] = e->tri2edg[3*tj+(ic+1)%3];
-            e->tri2edg[3*ttj+2] = e2;
-
-            e->tri2edg[3*tj+(ic+1)%3] = e2;
-            e->tri2edg[3*tj+ic] = e0;
-
-            uint64_t *t_ = &e->edg2tri[2*e->tri2edg[3*ttj+1]];
-            if(t_[0]==tj)
-              t_[0] = ttj;
-            else
-              t_[1] = ttj;
-
-
-          }
-          else if (m->triangles.node[3*tj+ic]==ni && m->triangles.node[3*tj+(ic+1)%3]==nj){
-
-            m->triangles.node[3*tj+ic] = m->vertices.num-1;
-
-            m->triangles.node[3*ttj+0] = ni;
-            m->triangles.node[3*ttj+1] = m->vertices.num-1;
-            m->triangles.node[3*ttj+2] = m->triangles.node[3*tj+(ic+2)%3];
-            e->tri2edg[3*ttj+0] = ei;
-            e->tri2edg[3*ttj+1] = e2;
-            e->tri2edg[3*ttj+2] = e->tri2edg[3*tj+(ic+2)%3];
-
-            e->tri2edg[3*tj+ic] = e0;
-            e->tri2edg[3*tj+(ic+2)%3] = e2;
-
-            uint64_t *t_ = &e->edg2tri[2*e->tri2edg[3*ttj+2]];
-            if(t_[0]==tj)
-              t_[0] = ttj;
-            else
-              t_[1] = ttj;    
-
-          }
-        }//end for      
-        e->numEdges +=3;
-        if(e->numEdges > maxEdg){
-          maxEdg *= 2;
-          HXT_CHECK(hxtRealloc(&e->node,2*maxEdg*sizeof(uint32_t)));
-          HXT_CHECK(hxtRealloc(&e->color,maxEdg*sizeof(uint16_t)));
-          HXT_CHECK(hxtRealloc(&e->edg2tri,2*maxEdg*sizeof(uint64_t)));
-        }
-        e->node[2*ei+1] = m->vertices.num-1;
-        e->edg2tri[2*ei+0] = ti;
-        e->edg2tri[2*ei+1] = ttj;       
-        e->node[2*e0+0] = m->vertices.num-1;
-        e->node[2*e0+1] = nj;
-        e->edg2tri[2*e0+0] = tti;
-        e->edg2tri[2*e0+1] = tj;
-        e->node[2*e1+0] = m->vertices.num-1;
-        e->node[2*e1+1] = m->triangles.node[3*tti+2];
-        e->edg2tri[2*e1+0] = ti;
-        e->edg2tri[2*e1+1] = tti;
-        e->node[2*e2+0] = m->vertices.num-1;
-        e->node[2*e2+1] = m->triangles.node[3*ttj+2];
-        e->edg2tri[2*e2+0] = tj;
-        e->edg2tri[2*e2+1] = ttj;
-
-
-        if (ti < initialNumberOfTriangles)
-          flag[ti] = 1;
-        if (tj < initialNumberOfTriangles)
-          flag[tj] = 1;
-
-      }// end while flag[it]==0
-    }//end for it
-
-
-    /*
-    if(threshold>0)
-      for(uint64_t it=0; it<m->triangles.num; it++){
-        double l;
-        HXT_CHECK(hxtDoubleLongestEdge(e,it,&l));
-        if(l>2*threshold && nrefinements<10){
-          nrefinements++;
-          break;
-        }
-      }
-    */
-
-  }//end refinement
-
- 
-  
-
-  return HXT_STATUS_OK;
-}
-
-
-
-static uint64_t hxtLengthKey(uint32_t* edgeID, HXTEdges* edges){
-  double l = hxtEdgesLength(edges,*edgeID);
-  return double_to_u64(l);
-}
-
-
-HXTStatus hxtEdgeRefinement(HXTEdges *edges,int nrefinements)
-{
-
-  double threshold = 0, counter=0;
-  for(uint32_t ie=0; ie<edges->numEdges; ie++)
-    if(edges->edg2tri[2*ie+1]==(uint64_t)-1){
-      threshold+= hxtEdgesLength(edges,ie);
-      counter++;
-    }
-  if (counter>0)
-    threshold/=counter;
-  else{
-    for(uint32_t ie=0; ie<edges->numEdges; ie++)
-      threshold+= hxtEdgesLength(edges,ie);
-    threshold /= edges->numEdges;
-  }
-  threshold *= 2;
-
-  
-  //bisection of longest edges first; boundary edges are not splitted
-  for(int ir=0; ir<nrefinements; ir++){
-    HXTEdges *e = edges;
-    HXTMesh *m = edges->edg2mesh;
-
-
-
-    uint32_t* edgIdx = NULL;
-    HXT_CHECK(hxtMalloc(&edgIdx,edges->numEdges*sizeof(uint32_t)));
-
-    for(uint32_t edg=0; edg<edges->numEdges; edg++)
-      edgIdx[edg] = edg;
-
-    HXTSORT64_UNIFORM(uint32_t, edgIdx, edges->numEdges, UINT64_MAX, hxtLengthKey, edges);
-
-    
-    int maxVert = m->vertices.num;
-    int maxTri = m->triangles.num;
-    uint32_t initialNumberOfEdges = e->numEdges;
-    int  maxEdg = initialNumberOfEdges;
-    //splitting from longest edge to smallest one
-    //splitted edges were larger than thredshold
-    //boundary edges are never splitted
-    for(uint32_t edg=initialNumberOfEdges-1; edg>=0; edg--){
-      uint32_t ie = edgIdx[edg];
-      if(hxtEdgesLength(e,ie)<threshold)
-	break;
-      if(e->edg2tri[2*ie+1]==(uint64_t)-1)
-	continue;
-      m->vertices.num += 1;
-      if(m->vertices.num > maxVert){
-	maxVert *= 2;
-	HXT_CHECK(hxtAlignedRealloc(&m->vertices.coord,4*maxVert*sizeof(double)));
-      }
-      int ni = e->node[2*ie+0], nj = e->node[2*ie+1];
-      int ti = (int) e->edg2tri[2*ie+0], tj = (int) e->edg2tri[2*ie+1];
-      for(int xj=0; xj<3; xj++)
-	m->vertices.coord[4*(m->vertices.num-1)+xj] = ( m->vertices.coord[4*ni+xj] + m->vertices.coord[4*nj+xj] )/2.;
-
-      m->triangles.num +=2;
-      if(m->triangles.num > maxTri){
-	maxTri *= 2;
-	HXT_CHECK(hxtAlignedRealloc(&m->triangles.node,3*maxTri*sizeof(uint32_t)));
-	HXT_CHECK(hxtAlignedRealloc(&m->triangles.colors,maxTri*sizeof(uint16_t)));
-	HXT_CHECK(hxtRealloc(&e->tri2edg,3*maxTri*sizeof(uint32_t)));
-      }
-      int tti = m->triangles.num-2, ttj = tti+1;
-      int e0 = e->numEdges, e1=e0+1, e2=e1+1;
-      for(int ic=0; ic<3; ic++){
-	if(m->triangles.node[3*ti+ic]==ni && m->triangles.node[3*ti+(ic+1)%3]==nj){
-	  m->triangles.node[3*ti+(ic+1)%3] = m->vertices.num-1;
-
-	  m->triangles.node[3*tti+0] = m->vertices.num-1;
-	  m->triangles.node[3*tti+1] = nj;
-	  m->triangles.node[3*tti+2] = m->triangles.node[3*ti+(ic+2)%3];
-	  e->tri2edg[3*tti+0] = e0;
-	  e->tri2edg[3*tti+1] = e->tri2edg[3*ti+(ic+1)%3];
-	  e->tri2edg[3*tti+2] = e1;
-
-	  e->tri2edg[3*ti+(ic+1)%3] = e1;
-
-	  uint64_t *t_ = &e->edg2tri[2*e->tri2edg[3*tti+1]];
-	  if(t_[0]==ti)
-	    t_[0] = tti;
-	  else
-	    t_[1] = tti;
-
-	}
-	else if (m->triangles.node[3*ti+ic]==nj && m->triangles.node[3*ti+(ic+1)%3]==ni) {
-	  m->triangles.node[3*ti+ic] = m->vertices.num-1;
-
-	  m->triangles.node[3*tti+0] = nj;
-	  m->triangles.node[3*tti+1] = m->vertices.num-1;
-	  m->triangles.node[3*tti+2] = m->triangles.node[3*ti+(ic+2)%3];
-	  e->tri2edg[3*tti+0] = e0;
-	  e->tri2edg[3*tti+1] = e1;
-	  e->tri2edg[3*tti+2] = e->tri2edg[3*ti+(ic+2)%3];
-
-	  e->tri2edg[3*ti+(ic+2)%3] = e1;
-
-
-	  uint64_t *t_ = &e->edg2tri[2*e->tri2edg[3*tti+2]];
-	  if(t_[0]==ti)
-	    t_[0] = tti;
-	  else
-	    t_[1] = tti;
-
-	}
-	if(m->triangles.node[3*tj+ic]==nj && m->triangles.node[3*tj+(ic+1)%3]==ni){
-	  m->triangles.node[3*tj+(ic+1)%3] = m->vertices.num-1;
-
-	  m->triangles.node[3*ttj+0] = m->vertices.num-1;
-	  m->triangles.node[3*ttj+1] = ni;
-	  m->triangles.node[3*ttj+2] = m->triangles.node[3*tj+(ic+2)%3];
-	  e->tri2edg[3*ttj+0] = ie;
-	  e->tri2edg[3*ttj+1] = e->tri2edg[3*tj+(ic+1)%3];
-	  e->tri2edg[3*ttj+2] = e2;
-
-	  e->tri2edg[3*tj+(ic+1)%3] = e2;
-	  e->tri2edg[3*tj+ic] = e0;
-
-	  uint64_t *t_ = &e->edg2tri[2*e->tri2edg[3*ttj+1]];
-	  if(t_[0]==tj)
-	    t_[0] = ttj;
-	  else
-	    t_[1] = ttj;
-
-
-	}
-	else if (m->triangles.node[3*tj+ic]==ni && m->triangles.node[3*tj+(ic+1)%3]==nj){
-
-	  m->triangles.node[3*tj+ic] = m->vertices.num-1;
-
-	  m->triangles.node[3*ttj+0] = ni;
-	  m->triangles.node[3*ttj+1] = m->vertices.num-1;
-	  m->triangles.node[3*ttj+2] = m->triangles.node[3*tj+(ic+2)%3];
-	  e->tri2edg[3*ttj+0] = ie;
-	  e->tri2edg[3*ttj+1] = e2;
-	  e->tri2edg[3*ttj+2] = e->tri2edg[3*tj+(ic+2)%3];
-
-	  e->tri2edg[3*tj+ic] = e0;
-	  e->tri2edg[3*tj+(ic+2)%3] = e2;
-
-	  uint64_t *t_ = &e->edg2tri[2*e->tri2edg[3*ttj+2]];
-	  if(t_[0]==tj)
-	    t_[0] = ttj;
-	  else
-	    t_[1] = ttj;    
-
-	}
-      }//end for      
-      e->numEdges +=3;
-      if(e->numEdges > maxEdg){
-	maxEdg *= 2;
-	HXT_CHECK(hxtRealloc(&e->node,2*maxEdg*sizeof(uint32_t)));
-	HXT_CHECK(hxtRealloc(&e->color,maxEdg*sizeof(uint16_t)));
-	HXT_CHECK(hxtRealloc(&e->edg2tri,2*maxEdg*sizeof(uint64_t)));
-      }
-      e->node[2*ie+1] = m->vertices.num-1;
-      e->edg2tri[2*ie+0] = ti;
-      e->edg2tri[2*ie+1] = ttj;       
-      e->node[2*e0+0] = m->vertices.num-1;
-      e->node[2*e0+1] = nj;
-      e->edg2tri[2*e0+0] = tti;
-      e->edg2tri[2*e0+1] = tj;
-      e->node[2*e1+0] = m->vertices.num-1;
-      e->node[2*e1+1] = m->triangles.node[3*tti+2];
-      e->edg2tri[2*e1+0] = ti;
-      e->edg2tri[2*e1+1] = tti;
-      e->node[2*e2+0] = m->vertices.num-1;
-      e->node[2*e2+1] = m->triangles.node[3*ttj+2];
-      e->edg2tri[2*e2+0] = tj;
-      e->edg2tri[2*e2+1] = ttj;
-
-
-      
-      
-
-
-      
-    }//end for ie
-
-
-    
-    for(uint32_t ie=0; ie<e->numEdges; ie++)
-      if(hxtEdgesLength(e,ie)>threshold){
-	nrefinements++;
-	break;
-      }
-    
-  }//end for ir
-  printf("nrefinements:\t %d\n",nrefinements);
-  return HXT_STATUS_OK;
-}
-
-
diff --git a/contrib/hxt/hxt_bissection.h b/contrib/hxt/hxt_bissection.h
deleted file mode 100644
index f38fe702f3..0000000000
--- a/contrib/hxt/hxt_bissection.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef HEXTREME_BISSECTION_H
-#define HEXTREME_BISSECTION_H
-
-#include "hxt_tools.h"
-#include "hxt_mesh.h"
-#include "hxt_edge.h"
-
-
-HXTStatus hxtLongestEdgeBisection(HXTEdges *edges,int nrefinements);
-HXTStatus hxtEdgeRefinement(HXTEdges *edges,int nrefinements);
-#endif
diff --git a/contrib/hxt/hxt_boundary_recovery.h b/contrib/hxt/hxt_boundary_recovery.h
deleted file mode 100644
index b046b4a7a7..0000000000
--- a/contrib/hxt/hxt_boundary_recovery.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef _HXT_BOUNDARY_RECOVERY_
-#define _HXT_BOUNDARY_RECOVERY_
-HXTStatus hxt_boundary_recovery(HXTMesh *mesh);
-#endif
diff --git a/contrib/hxt/hxt_context.c b/contrib/hxt/hxt_context.c
deleted file mode 100644
index abf2bdbfaf..0000000000
--- a/contrib/hxt/hxt_context.c
+++ /dev/null
@@ -1,19 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include "hxt_tools.h"
-#include "hxt_context.h"
-
-HXTStatus hxtInit(int argc, char **argv) {
-  return HXT_STATUS_OK;
-}
-
-HXTStatus  hxtContextCreate  ( HXTContext** ctxtPtr){
-  HXT_CHECK( hxtMalloc (ctxtPtr, sizeof(HXTContext)) );
-  return HXT_STATUS_OK;
-}
-
-
-HXTStatus  hxtContextDelete  ( HXTContext** ctxtPtr){
-  HXT_CHECK( hxtFree(ctxtPtr) );
-  return HXT_STATUS_OK;
-}
\ No newline at end of file
diff --git a/contrib/hxt/hxt_context.h b/contrib/hxt/hxt_context.h
deleted file mode 100644
index 212813efbf..0000000000
--- a/contrib/hxt/hxt_context.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _HXT_CONTEXT_T_
-#define _HXT_CONTEXT_T_
-#include "hxt_api.h"
-
-struct hxtContextStruct{
-  int emptyStructIsUndefinedBehaviorInC;
-};
-
-#endif
diff --git a/contrib/hxt/hxt_edgeRemoval.h b/contrib/hxt/hxt_edgeRemoval.h
deleted file mode 100644
index 7b672d2cb7..0000000000
--- a/contrib/hxt/hxt_edgeRemoval.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef _HXT_EDGEREMOVAL_
-#define _HXT_EDGEREMOVAL_
-
-#include "hxt_tetSync.h"
-#include "hxt_tetPartition.h"
-#include "hxt_tetQuality.h"
-#include "hxt_tetOptiDate.h"
-
-#define HXT_EDGE_REMOVAL_MAX 7 // you cannot increase it above 7 ATM
-
-typedef struct { // bipyramidal cavity for the edge-removal
-    uint64_t neigh_up  [HXT_EDGE_REMOVAL_MAX];
-    uint64_t neigh_down[HXT_EDGE_REMOVAL_MAX];
-    uint16_t flag      [HXT_EDGE_REMOVAL_MAX];
-    uint32_t annulus   [HXT_EDGE_REMOVAL_MAX];
-    uint32_t v_up;
-    uint32_t v_down;
-    uint32_t num;
-} HXTBipyramid;
-
-
-typedef struct {
-  HXTBipyramid cavity; // bipyramid cavity is specific to edge removal, that's why it is not a ptr
-  HXTDeleted* deleted;
-  HXTPartition* partition;
-  HXTTetQualities* quality;
-  HXTTetDates* date;
-  HXT2Sync* toSync;
-} HXTEdgeRemovalData;
-
-
-/* return internal error (that you must catch) if:
- *    - the cavity overlap different partitions  => HXT_STATUS_CONFLICT
- *    - there is a contraint inside the cavity   => HXT_STATUS_CONSTRAINT
- *    - does'nt result in a better triangulation => HXT_STATUS_NOTBETTER
- *    - there is more than 7 pts around the edge => HXT_STATUS_INTERNAL
- * a facet without neighbor (set to HXT_NO_ADJACENT) is also a constraint.
- */
-HXTStatus hxtEdgeRemoval_opti(HXTEdgeRemovalData* data,
-                              uint64_t badTet,
-                              unsigned edgeID);
-
-#endif
\ No newline at end of file
diff --git a/contrib/hxt/hxt_laplace.c b/contrib/hxt/hxt_laplace.c
deleted file mode 100644
index ce4d16dd60..0000000000
--- a/contrib/hxt/hxt_laplace.c
+++ /dev/null
@@ -1,159 +0,0 @@
-#include <math.h>
-#include "hxt_laplace.h"
-#include "hxt_mesh.h"
-
-#include "hxt_laplace.h"
-#include "hxt_api.h"
-#include "hxt_linear_system.h"
-
-/*
-   compute the element matrix for one P1 triangle
-   local matrix is \intE \nabla NI \cdot \nabla NJ ds
-     v
-   ^
-   |                F (u,v) = N_0 (u,v) F_0 + N_1 (u,v) F_1 + N_2 (u,v) F_2
-   + 2              FJ is the value of F at node j
-   |\               NJ ( uI, vI) = \delta_{ij} 
-   |  \             N_0 = 1-u-v ; N_1 = u ; N_2 = v
-   |    \           grad N = { { -1 , -1} , { 1 , 0} , { 0 , 1} };
-   |      \
-   |        \
-   |         \
-   |0  (0,0)  \ 1 (1,0)
-   +------------+--------> u
-  
-    X_0, X_1, X_2 the three vertices of a triangle in XYZ coordinate system
-    X (u,v) = X_0 N_0 + X_1 N_1 + X_2 N_2             
-*/
-
-static inline double normalize (double *n){
-  double d = sqrt (n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);
-  if (d != 0.0){
-    n[0] /= d;
-    n[1] /= d;
-    n[2] /= d;
-  }
-  return fabs(d);
-}
-
-static inline void crossprod (double *a, double *b, double *n){
-  n[0] = a[1]*b[2] - a[2]*b[1]; 
-  n[1] = - (a[0]*b[2] - a[2]*b[0]); 
-  n[2] = a[0]*b[1] - a[1]*b[0]; 
-}
-
-
-static inline HXTStatus inverseJacobian ( double *X0, double *X1, double *X2, double invjac[3][3], double *det)
-{
-  double v1[3] = {X1[0]-X0[0],X1[1]-X0[1],X1[2]-X0[2]};
-  double v2[3] = {X2[0]-X0[0],X2[1]-X0[1],X2[2]-X0[2]};
-  double n[3] ; crossprod (v1,v2,n);
-  normalize (n);
-  double jac[3][3] = {{v1[0], v1[1], v1[2]},
-                      {v2[0], v2[1], v2[2]},
-                      {n[0] , n[1] , n[2]}};
-  HXT_CHECK(hxtInv3x3(jac, invjac,det));
-  return HXT_STATUS_OK;
-}
-
-static inline double dotprod (double *a, double *b){
-  return a[0]*b[0]+a[1]*b[1]+a[2]*b[2];
-}
-
-static inline void elementMatrix ( double *X0, double *X1, double *X2, double mat[9])
-{
-  double invjac[3][3], det;
-  inverseJacobian ( X0, X1, X2, invjac, &det);
-
-  double GradN0[3] = {-invjac[0][0]-invjac[0][1],-invjac[1][0]-invjac[1][1],-invjac[2][0]-invjac[2][1]};
-  double GradN1[3] = {invjac[0][0],invjac[1][0],invjac[2][0]};
-  double GradN2[3] = {invjac[0][1],invjac[1][1],invjac[2][1]};
-
-  mat[3*0+0] = dotprod(GradN0,GradN0) * det * .5;
-  mat[3*1+1] = dotprod(GradN1,GradN1) * det * .5;
-  mat[3*2+2] = dotprod(GradN2,GradN2) * det * .5;
-  
-  mat[3*0+1] = mat[3*1+0] = dotprod(GradN0,GradN1) * det * .5;
-  mat[3*0+2] = mat[3*2+0] = dotprod(GradN0,GradN2) * det * .5;
-  mat[3*1+2] = mat[3*2+1] = dotprod(GradN1,GradN2) * det * .5;
-}
-
-
-HXTStatus hxtLaplace(HXTMesh *mesh)
-{  
-  uint64_t nTriangles  = mesh->triangles.num;
-  uint64_t nEdgesBdry = mesh->lines.num;
-  uint64_t nVertices = mesh->vertices.num;
-  HXTLinearSystem *nrSys; 
-
-  HXT_CHECK(hxtLinearSystemCreateLU(&nrSys,nTriangles,3,1,mesh->triangles.node));
-
-  double *sol, *rhs;
-  HXT_CHECK(hxtMalloc(&sol,nVertices*sizeof(double)));
-  HXT_CHECK(hxtMalloc(&rhs,nVertices*sizeof(double)));
-
-  for(uint64_t i=0;i<nVertices;i++){
-    rhs[i] = 0.0;
-  }
-  
-  double mat[9];
-  
-  for(uint64_t i=0;i<nTriangles;i++){
-    uint32_t n0 = mesh->triangles.node[3*i+0];
-    uint32_t n1 = mesh->triangles.node[3*i+1];
-    uint32_t n2 = mesh->triangles.node[3*i+2];
-    elementMatrix ( mesh->vertices.coord + 4*n0,
-                     mesh->vertices.coord + 4*n1,
-                     mesh->vertices.coord + 4*n2, mat);
-    //    printf("xxx %d %d %d %d %d\n",i,n0,n1,n2, nVertices);
-    HXT_CHECK(hxtLinearSystemAddToMatrix(nrSys,i,i,mat));
-  }
-
-  
-  for(uint64_t i=0;i<nEdgesBdry;i++){
-    uint32_t n0 = mesh->lines.node[2*i+0];
-    uint32_t n1 = mesh->lines.node[2*i+1];
-    double *X0 =  mesh->vertices.coord + 4*n0;
-    double *X1 =  mesh->vertices.coord + 4*n1;
-    double V0 = X0[1];
-    double V1 = X1[1];
-    HXT_CHECK(hxtLinearSystemSetMatrixRowIdentity(nrSys,n0,0));
-    HXT_CHECK(hxtLinearSystemSetMatrixRowIdentity(nrSys,n1,0));
-    HXT_CHECK(hxtLinearSystemSetRhsEntry(nrSys,rhs,n0,0,V0));
-    HXT_CHECK(hxtLinearSystemSetRhsEntry(nrSys,rhs,n1,0,V1));
-    
-    // according to your elementary entities, you can set your Dirichlet conditions
-    // here 1 and 3 is your elementary entities numbers
-    /*if(mesh->lines.colors[i] == 1){
-      HXT_CHECK(hxtLinearSystemSetRhsEntry(nrSys,rhs,n0,0,0.));
-      HXT_CHECK(hxtLinearSystemSetRhsEntry(nrSys,rhs,n1,0,0.));
-    }
-    if(mesh->lines.colors[i] == 3){
-      HXT_CHECK(hxtLinearSystemSetRhsEntry(nrSys,rhs,n0,0,1.));
-      HXT_CHECK(hxtLinearSystemSetRhsEntry(nrSys,rhs,n1,0,1.));
-    }*/
-  }
-
-  HXT_CHECK(hxtLinearSystemSolve(nrSys,rhs,sol));
-
-  FILE *f = fopen("a.pos","w");
-  fprintf(f,"View \"\"{\n");
-  for(uint64_t i=0;i<nTriangles;i++){
-    int n0 = mesh->triangles.node[3*i+0];
-    int n1 = mesh->triangles.node[3*i+1];
-    int n2 = mesh->triangles.node[3*i+2];
-    double *X0 =  mesh->vertices.coord +4*n0;
-    double *X1 =  mesh->vertices.coord +4*n1;
-    double *X2 =  mesh->vertices.coord +4*n2;
-    fprintf(f,"ST(%g,%g,%g,%g,%g,%g,%g,%g,%g){%g,%g,%g};\n",X0[0],X0[1],X0[2],X1[0],X1[1],X1[2],X2[0],X2[1],X2[2],sol[n0],sol[n1],sol[n2]);
-  }
-  fprintf(f,"};\n");
-  fclose(f);
-
-  HXT_CHECK(hxtFree(&rhs));
-  HXT_CHECK(hxtFree(&sol));
-  HXT_CHECK(hxtLinearSystemDelete(&nrSys));
-  
-
-  return HXT_STATUS_OK;
-}
diff --git a/contrib/hxt/hxt_laplace.h b/contrib/hxt/hxt_laplace.h
deleted file mode 100644
index b6f8a24c69..0000000000
--- a/contrib/hxt/hxt_laplace.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef HEXTREME_LAPLACE_H
-#define HEXTREME_LAPLACE_H
-
-#include "hxt_mesh.h"
-
-HXTStatus hxtLaplace(HXTMesh *mesh);
-
-#endif
diff --git a/contrib/hxt/hxt_mesh3d.c b/contrib/hxt/hxt_mesh3d.c
deleted file mode 100644
index 5fc35e353d..0000000000
--- a/contrib/hxt/hxt_mesh3d.c
+++ /dev/null
@@ -1,424 +0,0 @@
-// #include "hxt_mesh_size.h"
-#include "hxt_tetDelaunay.h"
-// #include "hxt_vertices.h"
-#include "hxt_mesh3d.h"
-#include "predicates.h"
-#include "hxt_tetFlag.h"
-
-// #if defined(_MSC_VER)
-// #define _CRT_RAND_S 
-// #include <stdlib.h> 
-// double drand48() {
-//   double a;
-//   rand_s(&a);
-//   return a;
-// }
-// #endif
-
-HXTStatus hxtCreateNodalSizeFromFunction(HXTMesh* mesh, HXTDelaunayOptions* delOptions,
-                                         double (*mesh_size)(double x, double y, double z, void* userData),
-                                         void* userData)
-{
-  HXT_CHECK(hxtAlignedMalloc(&delOptions->nodalSizes,mesh->vertices.num*sizeof(double)));
-
-  #pragma omp parallel for
-  for (uint32_t i=0; i<mesh->vertices.num; i++) {
-    double* coord = &mesh->vertices.coord[4*i];
-    delOptions->nodalSizes[i] = mesh_size(coord[0], coord[1], coord[2], userData);
-  }
-
-  return HXT_STATUS_OK;
-}
-
-
-HXTStatus hxtCreateNodalsizeFromTrianglesAndLines(HXTMesh* mesh, HXTDelaunayOptions* delOptions)
-{
-
-  HXT_CHECK(hxtAlignedMalloc(&delOptions->nodalSizes,mesh->vertices.num*sizeof(double))); 
-  
-  #pragma omp parallel for
-  for (uint32_t i = 0; i<mesh->vertices.num; i++){
-    delOptions->nodalSizes[i] = DBL_MAX;
-  }
-
-  // only do for triangles
-  // we do not take into account hereafter delOptions->nodalSizes = to DBL_MAX
-  // could be changed in another fashion
-  for (uint32_t i = 0; i<mesh->triangles.num; i++){
-    for (uint32_t j = 0; j<3; j++){  
-      for (uint32_t k = j+1; k<3; k++){  
-        uint32_t n1 = mesh->triangles.node[3*i+j];
-        uint32_t n2 = mesh->triangles.node[3*i+k];
-        if (n1 != HXT_GHOST_VERTEX && n2 != HXT_GHOST_VERTEX){
-          double *X1 = mesh->vertices.coord + (size_t) 4*n1;
-          double *X2 = mesh->vertices.coord + (size_t) 4*n2;
-          double l = sqrt ((X1[0]-X2[0])*(X1[0]-X2[0])+
-                           (X1[1]-X2[1])*(X1[1]-X2[1])+
-                           (X1[2]-X2[2])*(X1[2]-X2[2]));
-          if(l<delOptions->nodalSizes[n1]) delOptions->nodalSizes[n1] = l;
-          if(l<delOptions->nodalSizes[n2]) delOptions->nodalSizes[n2] = l;
-        }
-      }
-    }
-  }
-
-  for (uint32_t i = 0; i<mesh->lines.num; i++){
-      uint32_t n1 = mesh->lines.node[2*i+0];
-      uint32_t n2 = mesh->lines.node[2*i+1];
-      if (n1 != HXT_GHOST_VERTEX && n2 != HXT_GHOST_VERTEX){
-        double *X1 = mesh->vertices.coord + (size_t) 4*n1;
-        double *X2 = mesh->vertices.coord + (size_t) 4*n2;
-        double l = sqrt ((X1[0]-X2[0])*(X1[0]-X2[0])+
-                         (X1[1]-X2[1])*(X1[1]-X2[1])+
-                         (X1[2]-X2[2])*(X1[2]-X2[2]));
-        if(l<delOptions->nodalSizes[n1]) delOptions->nodalSizes[n1] = l;
-        if(l<delOptions->nodalSizes[n2]) delOptions->nodalSizes[n2] = l;
-    }
-  }
-  return HXT_STATUS_OK;    
-}
-
-HXTStatus hxtCreateNodalsizeFromMesh(HXTMesh* mesh, HXTDelaunayOptions* delOptions)
-{
-
-  HXT_CHECK(hxtAlignedMalloc(&delOptions->nodalSizes,mesh->vertices.num*sizeof(double))); 
-  
-  #pragma omp parallel for
-  for (uint32_t i = 0; i<mesh->vertices.num; i++){
-    delOptions->nodalSizes[i] = DBL_MAX;
-  }
-
-  // only do for triangles
-  // we do not take into account hereafter delOptions->nodalSizes = to DBL_MAX
-  // could be changed in another fashion
-  for (uint32_t i = 0; i<mesh->tetrahedra.num; i++){
-    for (uint32_t j = 0; j<4; j++){  
-      for (uint32_t k = j+1; k<4; k++){  
-        uint32_t n1 = mesh->tetrahedra.node[4*i+j];
-        uint32_t n2 = mesh->tetrahedra.node[4*i+k];
-        if (n1 != HXT_GHOST_VERTEX && n2 != HXT_GHOST_VERTEX){
-          double *X1 = mesh->vertices.coord + (size_t) 4*n1;
-          double *X2 = mesh->vertices.coord + (size_t) 4*n2;
-          double l = sqrt ((X1[0]-X2[0])*(X1[0]-X2[0])+
-               (X1[1]-X2[1])*(X1[1]-X2[1])+
-               (X1[2]-X2[2])*(X1[2]-X2[2]));
-          if(l<delOptions->nodalSizes[n1]) delOptions->nodalSizes[n1] = l;
-          if(l<delOptions->nodalSizes[n2]) delOptions->nodalSizes[n2] = l;
-        }
-      }
-    }
-  }
-  return HXT_STATUS_OK;
-}
-
-HXTStatus hxtDestroyNodalsize(HXTDelaunayOptions* delOptions)
-{
-  HXT_CHECK( hxtAlignedFree(&delOptions->nodalSizes) );
-  return HXT_STATUS_OK;
-}
-
-
-
-
-HXTStatus hxtEmptyMesh(HXTMesh* mesh, HXTDelaunayOptions* delOptions)
-{
-// we assume that the input is a surface mesh
-  if (mesh->tetrahedra.num)  
-    return HXT_ERROR_MSG(HXT_STATUS_FAILED, "The input mesh should only contain triangles");
-  if (mesh->triangles.num == 0)  
-    return HXT_ERROR_MSG(HXT_STATUS_FAILED, "The input mesh should contain triangles");
-
-  double minDist2 = DBL_MAX;
-  #pragma omp parallel for reduction(min:minDist2)
-  for (uint64_t i=0; i<mesh->triangles.num; i++){
-    uint32_t* node = mesh->triangles.node + 3*i;
-    for (int j=0; j<3; j++) {
-      double* n1 = mesh->vertices.coord + (size_t) 4*node[j];
-      double* n2 = mesh->vertices.coord + (size_t) 4*node[(j+1)%3];
-
-      double dist2 = (n1[0]-n2[0])*(n1[0]-n2[0])
-                   + (n1[1]-n2[1])*(n1[1]-n2[1])
-                   + (n1[2]-n2[2])*(n1[2]-n2[2]);
-
-      if(dist2<minDist2)
-        minDist2 = dist2;
-    }
-  }
-
-  double minSize = sqrt(minDist2);
-
-  hxtNodeInfo* nodeInfo;
-  HXT_CHECK( hxtAlignedMalloc(&nodeInfo, sizeof(hxtNodeInfo)*mesh->vertices.num) );
-
-#if !defined(HAVE_NO_OPENMP_SIMD)
-  #pragma omp parallel for simd aligned(nodeInfo:SIMD_ALIGN)
-#endif
-  for (uint32_t i=0; i<mesh->vertices.num; i++) {
-    nodeInfo[i].node = i;
-    nodeInfo[i].status = HXT_STATUS_TRYAGAIN;
-  }
-
-  delOptions->minSizeStart = 0.0;
-  delOptions->minSizeEnd = minSize;
-  HXT_CHECK( hxtDelaunaySteadyVertices(mesh, delOptions, nodeInfo, mesh->vertices.num) );
-  delOptions->minSizeStart = minSize;
-  delOptions->minSizeEnd = minSize;
-  delOptions->numVerticesInMesh = mesh->vertices.num;
-
-#ifdef DEBUG
-#if !defined(HAVE_NO_OPENMP_SIMD)
-  #pragma omp parallel for simd aligned(nodeInfo:SIMD_ALIGN)
-#endif
-  for (uint32_t i=0; i<mesh->vertices.num; i++) {
-    if(nodeInfo[i].status!=HXT_STATUS_TRUE){
-      HXT_WARNING("vertex %u of the empty mesh was not inserted\n", nodeInfo[i].node);
-    }
-  }
-#endif
-
-  HXT_CHECK( hxtAlignedFree(&nodeInfo) );
-  
-  return HXT_STATUS_OK;
-}
-
-
-
-// refine 
-
-
-double hxtTetCircumcenter(double a[3], double b[3], double c[3], double d[3],
-                            double circumcenter[3], double *xi, double *eta, double *zeta)
-{
-  double xba, yba, zba, xca, yca, zca, xda, yda, zda;
-  double balength, calength, dalength;
-  double xcrosscd, ycrosscd, zcrosscd;
-  double xcrossdb, ycrossdb, zcrossdb;
-  double xcrossbc, ycrossbc, zcrossbc;
-  double denominator;
-  double xcirca, ycirca, zcirca;
-
-  /* Use coordinates relative to point `a' of the tetrahedron. */
-  xba = b[0] - a[0];
-  yba = b[1] - a[1];
-  zba = b[2] - a[2];
-  xca = c[0] - a[0];
-  yca = c[1] - a[1];
-  zca = c[2] - a[2];
-  xda = d[0] - a[0];
-  yda = d[1] - a[1];
-  zda = d[2] - a[2];
-  /* Squares of lengths of the edges incident to `a'. */
-  balength = xba * xba + yba * yba + zba * zba;
-  calength = xca * xca + yca * yca + zca * zca;
-  dalength = xda * xda + yda * yda + zda * zda;
-  /* Cross products of these edges. */
-  xcrosscd = yca * zda - yda * zca;
-  ycrosscd = zca * xda - zda * xca;
-  zcrosscd = xca * yda - xda * yca;
-  xcrossdb = yda * zba - yba * zda;
-  ycrossdb = zda * xba - zba * xda;
-  zcrossdb = xda * yba - xba * yda;
-  xcrossbc = yba * zca - yca * zba;
-  ycrossbc = zba * xca - zca * xba;
-  zcrossbc = xba * yca - xca * yba;
-
-  /* Calculate the denominator of the formulae. */
-  /* Use orient3d() from http://www.cs.cmu.edu/~quake/robust.html     */
-  /*   to ensure a correctly signed (and reasonably accurate) result, */
-  /*   avoiding any possibility of division by zero.                  */
-  const double xxx =  orient3d(b, c, d, a);
-  denominator = 0.5 / xxx;
-
-  /* Calculate offset (from `a') of circumcenter. */
-  xcirca = (balength * xcrosscd + calength * xcrossdb + dalength * xcrossbc) *
-    denominator;
-  ycirca = (balength * ycrosscd + calength * ycrossdb + dalength * ycrossbc) *
-    denominator;
-  zcirca = (balength * zcrosscd + calength * zcrossdb + dalength * zcrossbc) *
-    denominator;
-  circumcenter[0] =  xcirca + a[0];
-  circumcenter[1] =  ycirca + a[1];
-  circumcenter[2] =  zcirca + a[2];
-
-  /*
- printf(" %g %g %g %g\n",
-         sqrt((a[0]-xcirca)*(a[0]-xcirca)+(a[1]-ycirca)*(a[1]-ycirca)+(a[2]-zcirca)*(a[2]-zcirca)),
-         sqrt((b[0]-xcirca)*(b[0]-xcirca)+(b[1]-ycirca)*(b[1]-ycirca)+(b[2]-zcirca)*(b[2]-zcirca)),
-         sqrt((c[0]-xcirca)*(c[0]-xcirca)+(c[1]-ycirca)*(c[1]-ycirca)+(c[2]-zcirca)*(c[2]-zcirca)),
-         sqrt((d[0]-xcirca)*(d[0]-xcirca)+(d[1]-ycirca)*(d[1]-ycirca)+(d[2]-zcirca)*(d[2]-zcirca)) );
-  */
-
-  if (xi != (double *) NULL) {
-    /* To interpolate a linear function at the circumcenter, define a    */
-    /*   coordinate system with a xi-axis directed from `a' to `b',      */
-    /*   an eta-axis directed from `a' to `c', and a zeta-axis directed  */
-    /*   from `a' to `d'.  The values for xi, eta, and zeta are computed */
-     /*   by Cramer's Rule for solving systems of linear equations.       */
-    *xi = (xcirca * xcrosscd + ycirca * ycrosscd + zcirca * zcrosscd) *
-      (2.0 * denominator);
-    *eta = (xcirca * xcrossdb + ycirca * ycrossdb + zcirca * zcrossdb) *
-      (2.0 * denominator);
-    *zeta = (xcirca * xcrossbc + ycirca * ycrossbc + zcirca * zcrossbc) *
-      (2.0 * denominator);
-  }
-  return xxx;
-}
-
-
-static HXTStatus hxtRefineTetrahedraOneStep(HXTMesh* mesh, HXTDelaunayOptions* delOptions,
-                                            double (*mesh_size)(double x, double y, double z, void* userData),
-                                            void* userData , int *nbAdd, int iter)
-{
-  double *newVertices;
-  uint32_t *numCreated;
-  int maxThreads = omp_get_max_threads();
-  HXT_CHECK( hxtAlignedMalloc(&newVertices, sizeof(double)*4*mesh->tetrahedra.num) );
-  HXT_CHECK( hxtMalloc(&numCreated, maxThreads*sizeof(uint32_t)) );
-
-  
-  // TODO: creating multiple vertices per tetrahedron
-  uint32_t add = 0;
-  HXTStatus status = HXT_STATUS_OK;
-  #pragma omp parallel reduction(+:add)
-  {
-    int threadID = omp_get_thread_num();
-    uint32_t localAdd = 0;
-
-    
-    #pragma omp for schedule(static)
-    for (uint64_t i=0; i<mesh->tetrahedra.num; i++)
-    {
-      newVertices[(size_t) 4*i+3] = -1.0;
-      if (mesh->tetrahedra.colors[i] != UINT16_MAX && getProcessedFlag(mesh, i)==0){
-        double *a = mesh->vertices.coord + (size_t) 4*mesh->tetrahedra.node[4*i+0];
-        double *b = mesh->vertices.coord + (size_t) 4*mesh->tetrahedra.node[4*i+1];
-        double *c = mesh->vertices.coord + (size_t) 4*mesh->tetrahedra.node[4*i+2];
-        double *d = mesh->vertices.coord + (size_t) 4*mesh->tetrahedra.node[4*i+3];
-        double circumcenter [3];
-        double u,v,w;
-        hxtTetCircumcenter(a,b,c,d, circumcenter, &u, &v, &w);
-        double circumradius2 = (a[0]-circumcenter[0])*(a[0]-circumcenter[0])+
-                               (a[1]-circumcenter[1])*(a[1]-circumcenter[1])+
-                               (a[2]-circumcenter[2])*(a[2]-circumcenter[2]);
-
-        setProcessedFlag(mesh, i); // we do not need to refine that tetrahedra anymore
-
-        // all new edges will have a length equal to circumradius2
-        double meshSize;
-        //        HXTStatus status = hxtMeshSizeEvaluate ( sizeField, circumcenter, &meshSize);
-
-        if(u <= 0 || v <= 0 || w <= 0 || 1.-u-v-w <= 0)
-          continue;
-        
-        if(mesh_size!=NULL) {
-          meshSize = mesh_size(circumcenter[0], circumcenter[1], circumcenter[2], userData);
-        }
-        else { // we suppose delOptions->nodalSize!=NULL
-          double SIZES[4];
-          double AVG = 0;
-          int NN = 0;
-          for (int j=0;j<4;j++){
-            SIZES[j] = delOptions->nodalSizes[mesh->tetrahedra.node[4*i+j]];
-            if (SIZES[j] != DBL_MAX){
-              NN++;
-              AVG += SIZES[j];
-            }
-          }
-          if (NN != 4){
-            AVG /= NN;
-            for (int j=0;j<4;j++){
-              if (SIZES[j] == DBL_MAX){
-                // delOptions->nodalSizes[mesh->tetrahedra.node[4*i+j]] = AVG;
-                SIZES[j] = AVG;
-              }
-            }
-          }
-
-          meshSize = SIZES[0] * (1-u-v-w) + SIZES[1] * u + SIZES[2] * v + SIZES[3] * w;
-        }
-  
-        
-  
-        if (meshSize * meshSize /* .49*/ < circumradius2) {
-          //    printf("%llu %g\n",i,sqrt(circumradius2),meshSize);
-          newVertices[(size_t) 4*i  ] = circumcenter[0];
-          newVertices[(size_t) 4*i+1] = circumcenter[1];
-          newVertices[(size_t) 4*i+2] = circumcenter[2];
-          newVertices[(size_t) 4*i+3] = meshSize;
-          localAdd++;
-        }
-      }
-    }
-
-    numCreated[threadID] = localAdd;
-
-    #pragma omp barrier
-    #pragma omp single
-    {
-      int nthreads = omp_get_num_threads();
-      add = 0;
-      for (int i=0; i<nthreads; i++) {
-        uint32_t tsum = add + numCreated[i];
-        numCreated[i] = add;
-        add = tsum;
-      }
-
-      if(mesh->vertices.num + add>mesh->vertices.size){
-        status=hxtAlignedRealloc(&mesh->vertices.coord, sizeof(double)*4*(mesh->vertices.num + add));
-        if(status==HXT_STATUS_OK){
-          status=hxtAlignedRealloc(&delOptions->nodalSizes, (mesh->vertices.num + add)*sizeof(double));
-          mesh->vertices.size = mesh->vertices.num + add;
-        }
-      }
-    }
-
-    localAdd = numCreated[threadID] + mesh->vertices.num;
-
-    if(status==HXT_STATUS_OK){
-      #pragma omp for schedule(static)
-      for (uint64_t i=0; i<mesh->tetrahedra.num; i++){
-        if ( newVertices [4*i+3]!=-1.0 ) {
-          mesh->vertices.coord[ (size_t) 4*localAdd   ] = newVertices [(size_t) 4*i  ];
-          mesh->vertices.coord[ (size_t) 4*localAdd+1 ] = newVertices [(size_t) 4*i+1];
-          mesh->vertices.coord[ (size_t) 4*localAdd+2 ] = newVertices [(size_t) 4*i+2];
-          delOptions->nodalSizes[localAdd] = newVertices [4*i+3];
-          localAdd++;
-        }
-      }
-    }
-  }
-
-  if(status!=HXT_STATUS_OK){
-    HXT_TRACE(status);
-    return status;
-  }
-
-  mesh->vertices.num += add;
-
-
-  HXT_CHECK( hxtFree(&numCreated) );
-  HXT_CHECK(hxtAlignedFree(&newVertices));
-  
-  HXT_CHECK(hxtDelaunay(mesh, delOptions));
-
-  *nbAdd = mesh->vertices.num - delOptions->numVerticesInMesh;
-  delOptions->numVerticesInMesh = mesh->vertices.num;
-  return HXT_STATUS_OK;
-}
-
-HXTStatus hxtRefineTetrahedra(HXTMesh* mesh,
-                              HXTDelaunayOptions* delOptions,
-                              double (*mesh_size)(double x, double y, double z, void* userData),
-                              void* userData) {
-  int iter = 0;
-  while(iter++ < 40){
-    int nbAdd=0;
-    HXT_CHECK(hxtRefineTetrahedraOneStep(mesh, delOptions, mesh_size, userData, &nbAdd, iter));
-    //    uint32_t nb;
-    //    HXT_CHECK(hxtColorMesh(mesh,&nb));
-    if (nbAdd == 0) break;
-  }
-  return HXT_STATUS_OK;
-}
-
-
diff --git a/contrib/hxt/hxt_mesh3d.h b/contrib/hxt/hxt_mesh3d.h
deleted file mode 100644
index 23afb959df..0000000000
--- a/contrib/hxt/hxt_mesh3d.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef _HXT_MESH_3D_
-#define _HXT_MESH_3D_
-
-#include "hxt_tetDelaunay.h"
-
-/// Creates a structure that allows to look over triangular faces of the 2D mesh
-HXTStatus hxtCreateFaceSearchStructure(HXTMesh* mesh, uint32_t **pfaces);
-
-//// creates a mesh with all points of the surface mesh
-HXTStatus hxtEmptyMesh(HXTMesh* mesh, HXTDelaunayOptions* delOptions);
-
-/// Compute sizes at vertices of the mesh from a mesh_size function
-HXTStatus hxtCreateNodalSizeFromFunction(HXTMesh* mesh, HXTDelaunayOptions* delOptions,
-                                         double (*mesh_size)(double x, double y, double z, void* userData),
-                                         void* userData);
-
-/// Compute sizes at vertices of the mesh from existing edges
-HXTStatus hxtCreateNodalsizeFromTrianglesAndLines(HXTMesh* mesh, HXTDelaunayOptions* delOptions);
-HXTStatus hxtCreateNodalsizeFromMesh(HXTMesh* mesh, HXTDelaunayOptions* delOptions);
-HXTStatus hxtDestroyNodalsize(HXTDelaunayOptions* delOptions);
-
-/// Add points at tets circumcenter in order to fullfill a mesh size constraint 
-HXTStatus hxtRefineTetrahedra(HXTMesh* mesh,
-                              HXTDelaunayOptions* delOptions,
-                              double (*mesh_size)(double x, double y, double z, void* userData),
-                              void* userData);
-
-#endif
diff --git a/contrib/hxt/hxt_mesh3d_main.c b/contrib/hxt/hxt_mesh3d_main.c
deleted file mode 100644
index a5f3df74ff..0000000000
--- a/contrib/hxt/hxt_mesh3d_main.c
+++ /dev/null
@@ -1,166 +0,0 @@
-#include "hxt_mesh3d.h"
-#include "hxt_tetDelaunay.h"
-#include "hxt_tetRepair.h"
-#include "hxt_tetUtils.h"
-#include "hxt_tetFlag.h"
-#include "hxt_tetColor.h"
-#include "hxt_tetOpti.h"
-
-
-HXTStatus hxtTetMesh3d(HXTMesh* mesh,
-                      int defaulThreads,
-                      int DelaunayThreads,
-                      int optimizationThreads,
-                      int reproducible,
-                      int verbosity,
-                      int displayStat,
-                      int refine,
-                      int optimize,
-                      double qualityThreshold,
-                      HXTStatus (*bnd_recovery)(HXTMesh* mesh),
-                      double (*mesh_size)(double x, double y, double z, void* userData),
-                      void* userData) {
-
-  if(defaulThreads>0) {
-    omp_set_num_threads(defaulThreads);
-  }
-
-  double t[8]={0};
-  t[0] = omp_get_wtime();
-
-  HXTBbox bbox;
-  hxtBboxInit(&bbox);
-  HXT_CHECK( hxtBboxAdd(&bbox, mesh->vertices.coord, mesh->vertices.num) );
-
-  HXTDelaunayOptions delOptions = {&bbox, NULL, 0.0, 0.0, 0, verbosity, reproducible, DelaunayThreads};
-  uint32_t numVerticesConstrained = mesh->vertices.num;
-  
-  HXT_INFO_COND(verbosity>0, "Creating an empty mesh with %u vertices", numVerticesConstrained);
-  HXT_CHECK( hxtEmptyMesh(mesh, &delOptions) );
-
-  t[1] = omp_get_wtime();
-
-  uint64_t nbMissingTriangles, nbLinesNotInTriangles, nbMissingLines=0;
-  uint16_t nbColors;
-  uint64_t* tri2TetMap = NULL;
-  uint64_t* lines2TriMap = NULL;
-  uint64_t* lines2TetMap = NULL;
-
-  HXT_CHECK( hxtAlignedMalloc(&tri2TetMap, mesh->triangles.num*sizeof(uint64_t)) );
-  HXT_CHECK( hxtAlignedMalloc(&lines2TriMap, mesh->lines.num*sizeof(uint64_t)) );
-  
-  HXT_CHECK( hxtGetTri2TetMap(mesh, tri2TetMap, &nbMissingTriangles) );
-  HXT_CHECK( hxtGetLines2TriMap(mesh, lines2TriMap, &nbLinesNotInTriangles) );
-
-  if(nbLinesNotInTriangles!=0) {
-    HXT_CHECK( hxtAlignedMalloc(&lines2TetMap, mesh->lines.num*sizeof(uint64_t)) );
-    if(nbMissingTriangles==0) {
-      HXT_CHECK( hxtGetLines2TetMap(mesh, lines2TetMap, &nbMissingLines) );
-    }
-  }
-
-
-  t[2] = omp_get_wtime();
-
-  if (nbMissingTriangles!=0 || nbMissingLines!=0){
-    if(bnd_recovery==NULL)
-      return HXT_ERROR_MSG(HXT_STATUS_ERROR,
-        "there are missing features but no boundary recovery function is given");
-
-    if(nbMissingTriangles)
-      HXT_INFO("Recovering %lu missing facet(s)", nbMissingTriangles);
-    else if(nbMissingLines)
-      HXT_INFO("Recovering %lu missing edge(s)", nbMissingLines);
-
-    HXT_CHECK(bnd_recovery(mesh));
-
-    if(delOptions.numVerticesInMesh < mesh->vertices.num) {
-      HXT_INFO("Steiner(s) point(s) were inserted");
-      delOptions.numVerticesInMesh = mesh->vertices.num;
-    }
-
-    t[3] = omp_get_wtime();
-
-    HXT_CHECK( hxtGetTri2TetMap(mesh, tri2TetMap, &nbMissingTriangles) );
-    if(nbMissingTriangles!=0)
-      return HXT_ERROR_MSG( HXT_STATUS_ERROR,
-        "%d boundary face%s still missing (after recovery step).",
-        nbMissingTriangles, (nbMissingTriangles>1)?"s are":" is" );
-
-    if(nbLinesNotInTriangles!=0)
-      HXT_CHECK( hxtGetLines2TetMap(mesh, lines2TetMap, &nbMissingLines) );
-
-    if(nbMissingLines!=0)
-      return HXT_ERROR_MSG( HXT_STATUS_ERROR,
-        "%d constrained edge%s still missing (after recovery step).",
-        nbMissingLines, (nbMissingLines>1)?"s are":" is" );
-  }
-
-  HXT_CHECK( hxtConstrainTriangles(mesh, tri2TetMap) );
-  
-  if(nbLinesNotInTriangles!=0)
-    HXT_CHECK( hxtConstrainLinesNotInTriangles(mesh, lines2TetMap, lines2TriMap) );
-
-  HXT_CHECK( hxtColorMesh(mesh, &nbColors) );
-
-  HXT_CHECK( hxtMapColorsToBrep(mesh, nbColors, tri2TetMap) );
-
-  HXT_CHECK( hxtAlignedFree(&tri2TetMap) );
-  HXT_CHECK( hxtAlignedFree(&lines2TetMap) );
-  HXT_CHECK( hxtAlignedFree(&lines2TriMap) );
-
-  t[4] = omp_get_wtime();
-
-  if(refine){
-    // HXT_CHECK(hxtComputeMeshSizeFromMesh(mesh, &delOptions));
-    if(mesh_size==NULL)
-    	HXT_CHECK(hxtCreateNodalsizeFromTrianglesAndLines(mesh, &delOptions));
-    else
-    	HXT_CHECK(hxtCreateNodalSizeFromFunction(mesh, &delOptions, mesh_size, userData) );
-
-    if(nbColors!=mesh->brep.numVolumes) {
-      HXT_CHECK( setFlagsToProcessOnlyVolumesInBrep(mesh) );
-    }
-
-    HXT_CHECK(hxtRefineTetrahedra(mesh, &delOptions, mesh_size, userData));
-
-    HXT_CHECK( hxtDestroyNodalsize(&delOptions) );
-  }
-
-  t[5] = omp_get_wtime();
-
-
-  if(optimize)
-    HXT_CHECK( hxtOptimizeTetrahedra(mesh, &bbox, optimizationThreads, delOptions.minSizeEnd, qualityThreshold, numVerticesConstrained) );
-
-  t[6] = omp_get_wtime();
-
-  
-  if(displayStat){
-    HXT_INFO("\n\t\tFinal tet. mesh contains %lu tetrahedra"
-             "\n\t\tand                      %u vertices", mesh->tetrahedra.num, mesh->vertices.num);
-
-    HXT_INFO("tEmptyMesh  \t = \t %8.3f", t[1]-t[0]);
-    HXT_INFO("tVerifyBnd  \t = \t %8.3f", t[2]-t[1]);
-    if(t[3]){
-      HXT_INFO("tBndRecovery\t = \t %8.3f", t[3]-t[2]);
-      HXT_INFO("tConvertMesh\t = \t %8.3f", t[4]-t[3]);
-      if(refine)
-        HXT_INFO("tRefine     \t = \t %8.3f", t[5]-t[4]);
-    }
-    else{
-      HXT_INFO("tBndRecovery\t = \t    0.000 (boundary not altered)");
-      HXT_INFO("tConvertMesh\t = \t    0.000 (nothing to convert)");
-      if(refine)
-        HXT_INFO("tRefine     \t = \t %8.3f", t[5]-t[2]);
-    }
-
-    if(!optimize)
-      HXT_INFO("tOptimize   \t = \t    0.000 (mesh optimization disabled)");
-    else
-      HXT_INFO("tOptimize   \t = \t %8.3f", t[6]-t[5]);
-  }
-
-  return HXT_STATUS_OK;
-}
-
diff --git a/contrib/hxt/hxt_mesh3d_main.h b/contrib/hxt/hxt_mesh3d_main.h
deleted file mode 100644
index f54e9001c6..0000000000
--- a/contrib/hxt/hxt_mesh3d_main.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef _HXT_MESH_3D_MAIN_
-#define _HXT_MESH_3D_MAIN_
-
-#include "hxt_mesh.h"
-
-HXTStatus hxtTetMesh3d(HXTMesh* mesh,
-                      int defaulThreads,
-                      int DelaunayThreads,
-                      int optimizationThreads,
-                      int reproducible,
-                      int verbosity,
-                      int displayStat,
-                      int refine,
-                      int optimize,
-                      double qualityThreshold,
-                      HXTStatus (*bnd_recovery)(HXTMesh* mesh),
-                      double (*mesh_size)(double x, double y, double z, void* userData),
-                      void* userData);
-
-#endif
\ No newline at end of file
diff --git a/contrib/hxt/hxt_mesh_size.c b/contrib/hxt/hxt_mesh_size.c
deleted file mode 100644
index 639dd09443..0000000000
--- a/contrib/hxt/hxt_mesh_size.c
+++ /dev/null
@@ -1,145 +0,0 @@
-#include "hxt_api.h"
-#include "hxt_tools.h"
-#include "hxt_mesh_size.h"
-#include <math.h>
-
-//typedef struct hxtMeshSizeStruct HXTMeshSize; // already defined in hxt_api.h
-
-HXTStatus hxtMeshSizeCellEvaluate(HXTMeshSizeCell *cell, double x, double y, double z, double *v) {
-  if (cell->isleaf){
-    *v = *(double*)cell->data;
-    return HXT_STATUS_OK;
-  }
-  HXTMeshSizeCell *sub = (HXTMeshSizeCell*)cell->data;
-  int i = x > 0.5 ? 1 : 0;
-  int j = y > 0.5 ? 1 : 0;
-  int k = z > 0.5 ? 1 : 0;
-  return hxtMeshSizeCellEvaluate(&sub[i*4+j*2+k],2*x-i, 2*y-j, 2*z-k, v);
-}
-
-HXTStatus hxtMeshSizeCreate (HXTContext* context, HXTMeshSize **meshSizePtr)
-{
-  HXTMeshSize *meshSize;
-  HXT_CHECK(
-    hxtMalloc(&meshSize, sizeof(HXTMeshSize)));
-
-  meshSize->context = context;
-  meshSize->root.data = NULL;
-  *meshSizePtr = meshSize;
-  return HXT_STATUS_OK;
-}
-
-HXTStatus hxtMeshSizeCellReleaseMemory(HXTMeshSizeCell *cell)
-{
-  if(!cell->data)
-    return HXT_STATUS_OK;
-  if(!cell->isleaf) {
-    HXTMeshSizeCell *sub = (HXTMeshSizeCell*) cell->data;
-    for (int i = 0; i < 8; ++i)
-      HXT_CHECK(hxtMeshSizeCellReleaseMemory(&sub[i]));
-  }
-  HXT_CHECK(hxtFree(&cell->data));
-  return HXT_STATUS_OK;
-}
-
-
-
-HXTStatus hxtMeshSizeCellInit(HXTMeshSizeCell *cell, double x0, double y0, double z0, double l, HXTMeshSizeCallback cb, void *data, int level) {
-#if 0
-  double v[8] = {
-    field(x0,y0,z0),field(x0,y0,z0+l),field(x0,y0+l,z0),field(x0,y0+l,z0+l),
-    field(x0+l,y0,z0),field(x0+l,y0,z0+l),field(x0+l,y0+l,z0),field(x0+l,y0+l,z0+l)
-  };
-  double dmax = 0;
-  double vmin = v[0];
-  double vc = field(x0+l/2,y0+l/2,z0+l/2);
-  for (int i = 0; i < 8; ++i){
-    dmax = fmax(dmax, std::abs(vc-v[i]));
-    vmin = fmin(vmin, v[i]);
-  }
-#else
-  double dmax = 0;
-  double x[3] = {x0+l/2, y0+l/2, z0+l/2};
-  double vc;
-  HXT_CHECK(cb(x, data, &vc));
-  double vmin = vc;
-  int split = level > 0;
-  if (level > -4) {
-#define NSAMPLE 4
-    double dl = l/NSAMPLE;
-    for (int i = 0; i <= NSAMPLE; ++i){
-      for (int j = 0; j <= NSAMPLE; ++j){
-        for (int k = 0; k <= NSAMPLE; ++k){
-          double xs[3] = {x0 + i*dl, y0+j*dl, z0+k*dl};
-          double w;
-          HXT_CHECK(cb(xs, data, &w));
-          dmax = fmax(dmax, fabs(vc-w));
-          vmin = fmin(vmin, w);
-          split |= (dmax/vmin > 0.2 && vmin < l);
-          if(split)
-            break;
-        }
-      }
-    }
-#endif
-  }
-  if (split) {
-    cell->isleaf = 0;
-    HXTMeshSizeCell *sub;
-    HXT_CHECK(hxtMalloc(&sub, sizeof(HXTMeshSizeCell)*8));
-    double l2 = l/2;
-    HXT_CHECK(hxtMeshSizeCellInit(sub+0, x0, y0, z0, l2, cb, data, level-1));
-    HXT_CHECK(hxtMeshSizeCellInit(sub+1, x0, y0, z0+l2, l2, cb, data, level-1));
-    HXT_CHECK(hxtMeshSizeCellInit(sub+2, x0, y0+l2, z0, l2, cb, data, level-1));
-    HXT_CHECK(hxtMeshSizeCellInit(sub+3, x0, y0+l2, z0+l2, l2, cb, data, level-1));
-    HXT_CHECK(hxtMeshSizeCellInit(sub+4, x0+l2, y0, z0, l2, cb, data, level-1));
-    HXT_CHECK(hxtMeshSizeCellInit(sub+5, x0+l2, y0, z0+l2, l2, cb, data, level-1));
-    HXT_CHECK(hxtMeshSizeCellInit(sub+6, x0+l2, y0+l2, z0, l2, cb, data, level-1));
-    HXT_CHECK(hxtMeshSizeCellInit(sub+7, x0+l2, y0+l2, z0+l2, l2, cb, data, level-1));
-    cell->data = (void*)sub;
-  }
-  else {
-    cell->isleaf = 1;
-    HXT_CHECK(hxtMalloc(&cell->data, sizeof(double)));
-    *(double*)cell->data = vc;
-  }
-  return HXT_STATUS_OK;
-}
-
-HXTStatus hxtMeshSizeDelete(HXTMeshSize **meshSizePtr)
-{
-  HXTMeshSize *meshSize = *meshSizePtr;
-  if (meshSize == NULL)
-    return HXT_STATUS_OK;
-  HXT_CHECK(hxtMeshSizeCellReleaseMemory(&meshSize->root));
-  HXT_CHECK(hxtFree(&meshSize));
-  *meshSizePtr = NULL;
-  return HXT_STATUS_OK;
-}
-
-HXTStatus hxtMeshSizeEvaluate(HXTMeshSize *meshSize, double x[3], double *v)
-{
-  if(!meshSize->root.data) {
-    //hxtMessageError(meshSize->context, "meshSize has not been computed\n");
-    return HXT_ERROR_MSG(HXT_STATUS_FAILED, "meshSize has not been computed");
-  }
-  double *bbmin = meshSize->bbmin;
-  double l = meshSize->l0;
-  HXT_CHECK(hxtMeshSizeCellEvaluate(&meshSize->root, (x[0]-bbmin[0])/l, (x[1]-bbmin[1])/l, (x[2]-bbmin[2])/l, v));
-  return HXT_STATUS_OK;
-}
-
-HXTStatus  hxtMeshSizeCompute( HXTMeshSize *meshSize , double min[3], double max[3], HXTMeshSizeCallback cb, void *data)
-{
-  if (meshSize->root.data) {
-    HXT_CHECK(hxtMeshSizeCellReleaseMemory(&meshSize->root));
-  }
-  for (int i = 0; i < 3; ++i) {
-    meshSize->bbmin[i] = min[i];
-    meshSize->bbmax[i] = max[i];
-  }
-  double l = fmax(max[0]-min[0], fmax(max[1]-min[1], max[2]-min[2]));
-  meshSize->l0 = l;
-  HXT_CHECK(hxtMeshSizeCellInit(&meshSize->root,min[0],min[1],min[2],l, cb, data, 4));
-  return HXT_STATUS_OK;
-}
diff --git a/contrib/hxt/hxt_mesh_size.h b/contrib/hxt/hxt_mesh_size.h
deleted file mode 100644
index ef669795d9..0000000000
--- a/contrib/hxt/hxt_mesh_size.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef _HXT_MESH_SIZE_H_
-#define _HXT_MESH_SIZE_H_
-
-#include "hxt_api.h"
-
-typedef struct {
-  void *data;
-  int isleaf;
-} HXTMeshSizeCell;
-
-struct hxtMeshSizeStruct {
-  HXTMeshSizeCell root;
-  double bbmin[3], bbmax[3];
-  double l0;
-  HXTContext* context;
-};
-
-#endif
diff --git a/contrib/hxt/hxt_octree_api.h b/contrib/hxt/hxt_octree_api.h
deleted file mode 100644
index 70d01e0c69..0000000000
--- a/contrib/hxt/hxt_octree_api.h
+++ /dev/null
@@ -1,53 +0,0 @@
-#ifndef _HXT_OCTREE_API_H_
-#define _HXT_OCTREE_API_H_
-
-#include <vector>
-extern "C" {
-#include "hxt_api.h"
-#include "hxt_bbox.h"
-}
-
-struct HXTForest;
-struct HXTForestOptions;
-
-HXTStatus hxtOctreeRefineSizeVariation(HXTForest *forest, int recursive);
-HXTStatus hxtOctreeCoarsenSizeVariation(HXTForest *forest, int recursive);
-HXTStatus hxtOctreeRefineToLevel(HXTForest *forest, int lvl);
-HXTStatus hxtOctreeInitialRefine(HXTForest *forest, int nRefine);
-HXTStatus hxtOctreeComputeLaplacian(HXTForest *forest);
-
-// HXTStatus hxtOctreeRefineLaplacian(HXTForest *forest);
-HXTStatus hxtOctreeCoarsenLaplacian(HXTForest *forest, int recursive);
-HXTStatus hxtOctreeLaplacianRefine(HXTForest *forest, int nRefine);
-
-// HXTStatus hxtOctreeBalance(HXTForest *forest);
-
-HXTStatus hxtOctreeSetMaxGradient(HXTForest *forest);
-HXTStatus hxtOctreeSmoothGradient(HXTForest *forest, int nMax);
-
-HXTStatus hxtOctreeComputeMaxGradientX(HXTForest *forest, double* dsdx_max);
-HXTStatus hxtOctreeComputeMaxGradientY(HXTForest *forest, double* dsdy_max);
-HXTStatus hxtOctreeComputeMaxGradientZ(HXTForest *forest, double* dsdz_max);
-HXTStatus hxtOctreeComputeMinimumSize(HXTForest *forest, double* size_min);
-
-HXTStatus hxtForestOptionsCreate(HXTForestOptions **forestOptions);
-HXTStatus hxtForestOptionsDelete(HXTForestOptions **forestOptions);
-
-// HXTStatus hxtForestCreate(int argc, char **argv, HXTForest **forest, const char* filename, void *user_pointer);
-HXTStatus hxtForestCreate(int argc, char **argv, HXTForest **forest, const char* filename, HXTForestOptions *forestOptions);
-HXTStatus hxtForestDelete(HXTForest **forest);
-
-HXTStatus hxtForestWriteBBoxMesh(HXTBbox *bbox, const char* filename);
-
-HXTStatus hxtOctreeRTreeIntersection(HXTForest *forest);
-
-HXTStatus hxtOctreeCurvatureRefine(HXTForest *forest, int nMax);
-
-HXTStatus hxtOctreeSearchOne(HXTForest *forest, double x, double y, double z, double *size);
-HXTStatus hxtOctreeSearch(HXTForest *forest, std::vector<double> *x, std::vector<double> *y, std::vector<double> *z, std::vector<double> *size);
-
-HXTStatus hxtOctreeSurfacesProches(HXTForest *forest);
-
-HXTStatus hxtOctreeElementEstimation(HXTForest *forest, double *elemEstimate);
-
-#endif
diff --git a/contrib/hxt/hxt_opt.c b/contrib/hxt/hxt_opt.c
deleted file mode 100644
index 70257871d8..0000000000
--- a/contrib/hxt/hxt_opt.c
+++ /dev/null
@@ -1,812 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <float.h>
-#include <errno.h>
-#include <limits.h>
-#include "hxt_opt.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\"", 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\"", 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/hxt_opt.h b/contrib/hxt/hxt_opt.h
deleted file mode 100644
index 2fc77be450..0000000000
--- a/contrib/hxt/hxt_opt.h
+++ /dev/null
@@ -1,170 +0,0 @@
-#ifndef __HXT_OPT_H__
-#define __HXT_OPT_H__
-
-#include "hxt_tools.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/hxt_option.c b/contrib/hxt/hxt_option.c
deleted file mode 100644
index 090db3cee5..0000000000
--- a/contrib/hxt/hxt_option.c
+++ /dev/null
@@ -1,504 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include "hxt_option.h"
-
-static HXTOpt help_option     = {"h", "help", "Display this help message"};
-
-/*********************************************************************
-*  program structure                                                 *
-*********************************************************************/
-struct HXTOptProgramStruct {
-	const char* usage_line;
-	const char* start_description;
-	const char* end_description;
-	HXTOpt** opts;
-	size_t opt_length;
-	size_t opt_capacity;
-};
-
-
-/*********************************************************************
-*  Create a program                                                  *
-*********************************************************************/
-HXTStatus hxtOptProgCreate(HXTOptProgram** program_ptr,
-			   const char* usage_line,
-			   const char* start_description,
-			   const char* end_description)
-{
-	HXT_ASSERT(program_ptr!=NULL);
-
-	HXTOptProgram* program;
-	HXT_CHECK( hxtMalloc(&program, sizeof(HXTOptProgram)) );
-	*program_ptr = program;
-
-	program->usage_line = usage_line;
-	program->start_description = start_description;
-	program->end_description = end_description;
-	program->opts = NULL;
-	program->opt_length = 0;
-	program->opt_capacity = 0;
-
-	hxtOptProgAddOption(program, &help_option);
-
-	return HXT_STATUS_OK;
-}
-
-
-/*********************************************************************
-*  add an option to a program                                        *
-*********************************************************************/
-HXTStatus hxtOptProgAddOption(HXTOptProgram* program, HXTOpt* opt)
-{
-	HXT_ASSERT( program!=NULL );
-	HXT_ASSERT( opt!=NULL );
-
-	if(program->opt_length >= program->opt_capacity){
-		size_t newSize = program->opt_length?program->opt_length*2:16;
-		HXT_CHECK( hxtRealloc(&program->opts,
-					          sizeof(HXTOpt*) * newSize ) );
-		program->opt_capacity = newSize;
-	}
-
-	program->opts[program->opt_length++] = opt;
-
-	return HXT_STATUS_OK;
-}
-
-
-/*********************************************************************
-*  delete a program                                                  *
-*********************************************************************/
-HXTStatus hxtOptProgDelete(HXTOptProgram* program){
-	HXT_ASSERT( program!=NULL );
-	HXT_CHECK( hxtFree(&program->opts) );
-	HXT_CHECK( hxtFree(&program) );
-
-	return HXT_STATUS_OK;
-}
-
-
-/*********************************************************************
-*  search a long option inside the lists of a program                *
-*********************************************************************/
-static int searchLongOption(HXTOptProgram* program,
-			                const char* string)
-{
-	for (size_t i=0; i<program->opt_length; i++) {
-		if(program->opts[i]->longs!=NULL &&
-		   strcmp(program->opts[i]->longs, string)==0) {
-			return i;
-		}
-	}
-
-	return -1;
-}
-
-
-/*********************************************************************
-*  search a short option inside the lists of a program               *
-*********************************************************************/
-static int searchShortOption(HXTOptProgram* program,
-                             char c)
-{
-	for (size_t i=0; i<program->opt_length; i++) {
-		if(program->opts[i]->shorts!=NULL &&
-		   strchr(program->opts[i]->shorts, c)!=NULL) {
-			return i;
-		}
-	}
-
-	return 0;
-}
-
-static inline const char* getArgTypeName(ARG_TYPE t){
-	switch(t) {
-		case ARG_INT64 :
-			return "a 64-bit integer";
-		case ARG_INT32 :
-			return "a 32-bit integer";
-		case ARG_UINT32 :
-			return "a 32-bit unsigned integer";
-		case ARG_DOUBLE :
-			return "a float";
-		case ARG_FLOAT :
-			return "a double";
-		case ARG_POSITIVE_FLOAT :
-			return "a positive float";
-		case ARG_POSITIVE_DOUBLE :
-			return "a positive double";
-		case ARG_STRING :
-			return "a string";
-		default:
-			if(t>0)
-				return "an integer";
-			else
-				return "a string";
-	}
-}
-
-
-/*********************************************************************
-*  scan parameter and execute callback function for user options     *
-*********************************************************************/
-static HXTStatus doOption(HXTOpt* opt,
-                          const char* arg,
-                          void* state,
-                          char* optName)
-{
-	char* endptr = NULL;
-
-	int64_t integer = INT64_MIN;
-	double real = NAN;
-	const char* string = "\a";
-
-	
-	if(opt->argRequirement&1 ||
-	  (opt->argRequirement==ARG_OPTIONAL && arg!=NULL)) {
-		if(opt->argType>-4)
-			integer = strtol(arg, &endptr, 0);
-		else if(opt->argType>-8)
-			real = strtod(arg, &endptr);
-		else
-			string = arg;
-
-
-		if(errno == ERANGE){
-			return HXT_ERROR_MSG(HXT_STATUS_RANGE_ERROR,
-			       "cannot convert argument \"%s\" of option \"%s\" to %s (range overflow)",
-			       arg, optName, getArgTypeName(opt->argType));
-		}
-		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->argType));
-		}
-		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->argType));
-		}
-
-		switch(opt->argType){
-			case ARG_POSITIVE_INT64 :
-				if(integer<0)
-					return HXT_ERROR_MSG(HXT_STATUS_RANGE_ERROR,
-					       "cannot convert argument \"%s\" of option \"%s\" to %s (value was negative)",
-					       arg, optName, getArgTypeName(opt->argType));
-			break;
-			case ARG_INT32:
-			{
-				int32_t i32 = integer;
-				if(i32!=integer)
-					return HXT_ERROR_MSG(HXT_STATUS_RANGE_ERROR,
-					       "cannot convert argument \"%s\" of option \"%s\" to %s ((int32_t)%ld!=%ld)",
-					       arg, optName, getArgTypeName(opt->argType), integer, integer);
-			}
-			break;
-			case ARG_UINT32:
-			{
-				uint32_t u32 = integer;
-				if(u32!=integer)
-					return HXT_ERROR_MSG(HXT_STATUS_RANGE_ERROR,
-					       "cannot convert argument \"%s\" of option \"%s\" to %s ((uint32_t)%ld!=%ld)",
-					       arg, optName, getArgTypeName(opt->argType), integer, integer);
-			}
-			break;
-			case ARG_POSITIVE_DOUBLE:
-				if(real<0.0)
-					return HXT_ERROR_MSG(HXT_STATUS_RANGE_ERROR,
-					       "cannot convert argument \"%s\" of option \"%s\" to %s (value was negative)",
-					       arg, optName, getArgTypeName(opt->argType));
-			break;
-			case ARG_POSITIVE_FLOAT:
-				if(real<0.0)
-					return HXT_ERROR_MSG(HXT_STATUS_RANGE_ERROR,
-					       "cannot convert argument \"%s\" of option \"%s\" to %s (value was negative)",
-					       arg, optName, getArgTypeName(opt->argType));
-			/* fallthrough */
-			case ARG_FLOAT:
-			{
-				float f32 = real;
-				if(f32!=real)
-					return HXT_ERROR_MSG(HXT_STATUS_RANGE_ERROR,
-					       "cannot convert argument \"%s\" of option \"%s\" to %s ((float)%f!=%f)",
-					       arg, optName, getArgTypeName(opt->argType), real, real);
-			}
-			break;
-			default:
-				if(opt->argType>0 && ( integer > opt->argType || integer<0 ) )
-					return HXT_ERROR_MSG(HXT_STATUS_RANGE_ERROR,
-					       "cannot convert argument \"%s\" of option \"%s\" to an integer between 0 and %d",
-					       arg, optName, opt->argType);
-			break;
-
-		}
-	}
-
-	if(opt->argType>-4)
-		opt->integer = integer;
-	else if(opt->argType>-8)
-		opt->real = real;
-	else
-		opt->string = string;
-
-	if(opt->cb!=NULL){
-		HXTStatus err = opt->cb(opt, state);
-		if(err<0){
-		return HXT_ERROR_MSG(HXT_STATUS_ERROR,
-		       "argument \"%s\" of option \"%s\" triggered an error in callback",
-		       arg, optName);
-		}
-	}
-
-	return HXT_STATUS_OK;
-}
-
-
-HXTStatus hxtOptCalledWithoutArg(HXTOpt* opt){
-	if(opt->argType>-4) // integer type
-		return (opt->integer==INT64_MIN);
-	else if(opt->argType>-8)
-		return (opt->real==NAN);
-	else
-		return (opt->string[0]=='\a');
-}
-
-
-/*********************************************************************
-*  Function parsing argv                                             *
-*********************************************************************/
-HXTStatus hxtOptProgParse(HXTOptProgram* program,
-			  const int argc,
-			  char* argv[],
-			  void* state,
-			  int* optind)
-{
-	HXT_ASSERT(program!=NULL);
-	HXT_ASSERT(optind!=NULL);
-
-	int numarg = argc;
-	*optind = 1;
-	for (int i=1; i<numarg; i++) {
-		char *arg = NULL;
-		HXTOpt* opt = NULL;
-
-		if(argv[i][0]!='-' || (argv[i][0]=='-' && argv[i][1]=='\0')){
-			/* not opt, shift everything before this string */
-			arg = argv[i];
-			for (int j=i; j<argc-1; j++) {
-				argv[j] = argv[j+1];
-			}
-			argv[argc-1] = arg;
-			numarg--;
-			i--;
-		}
-		else if(argv[i][1]=='-') { /* long opt */
-			if(argv[i][2]=='\0') /* -- terminate argument parsing */
-				return HXT_STATUS_OK;
-
-			char* equalSign = strchr(argv[i]+2,'=');
-			
-			if(equalSign!=NULL){
-				*equalSign = '\0';
-				arg = equalSign + 1;
-			}
-
-			int num = searchLongOption(program, argv[i]+2);
-			if(num<0){
-				return HXT_ERROR_MSG(HXT_STATUS_FORMAT_ERROR,
-				       "option \"%s\" not found", argv[i]);
-			}
-			opt = program->opts[num];
-
-			if(equalSign!=NULL){
-				*equalSign = '=';
-				if(opt->argRequirement==ARG_NONE){
-					return HXT_ERROR_MSG(HXT_STATUS_FORMAT_ERROR,
-					       "option \"%s\" takes no argument", argv[i]);
-				}
-			}
-			else{
-				if(num==0) { // it's the help option
-					*optind = -1;
-					return HXT_STATUS_OK;
-				}
-				if(opt->argRequirement&1 && numarg<=i+1){
-					return HXT_ERROR_MSG(HXT_STATUS_FORMAT_ERROR,
-					       "options \"%s\" requires an argument", argv[i]);
-				}
-				else if(numarg>i+1 && (opt->argRequirement&1 || argv[i+1][0]!='-')) {
-					arg = argv[i+1];
-					i++;
-				}
-			}
-
-			HXT_CHECK( doOption(opt, arg, state, argv[i]) );
-		}
-		else{ /* short option */
-			int cond = argv[i][1];
-			for(int j=1; cond; j++){
-				int num = searchShortOption(program, 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){
-					*optind = -1;
-					return HXT_STATUS_OK;
-				}
-
-				opt = program->opts[num];
-
-				if(opt->argRequirement!=ARG_NONE){
-					if(cond){
-						arg = argv[i] + j+1;
-						cond = 0; // stop the loop
-					}
-					else if(opt->argRequirement&1 && numarg<=i+1){
-						return HXT_ERROR_MSG(HXT_STATUS_FORMAT_ERROR,
-						       "options \'%c\' in \"%s\" requires an argument", argv[i][j], argv[i]);
-					}
-					else if(numarg>i+1 && (opt->argRequirement==ARG_REQUIRED || argv[i+1][0]!='-')) {
-						arg = argv[i+1];
-						i++;
-					}
-				}
-
-				HXT_CHECK( doOption(opt, arg, state, optName) );
-			}
-		}
-		*optind = i+1;
-	}
-
-	for (size_t i=0; i<program->opt_length; i++) {
-		HXTOpt* opt = program->opts[i];
-		if(opt->argRequirement==ARG_NON_NULL_REQUIRED &&
-			 ((opt->argType>-4 && opt->integer==0) ||
-			  (opt->argType>-8 && opt->real==0.0)  ||
-			  (opt->argType<=-8 && opt->string==NULL)
-			 )
-			) {
-			if(opt->longs!=NULL)
-				return HXT_ERROR_MSG(HXT_STATUS_ERROR,
-				       "mandatory option \"--%s\" must have a non-null argument",
-				       opt->longs);
-			else
-				return HXT_ERROR_MSG(HXT_STATUS_ERROR,
-				       "mandatory option \'-%c\' must have a non-null argument",
-				       opt->shorts[0]);
-		}
-	}
-
-	return HXT_STATUS_OK;
-}
-
-
-#define MY_SPRINTF(...) *offset+=snprintf(text+ *offset, 16384- *offset, ## __VA_ARGS__ )
-
-static void printOptionLine(HXTOpt* opt, char text[16384], int* offset)
-{
-	int char_max = 30;
-	int oldOffset = *offset;
-	MY_SPRINTF("  ");
-
-	int long_exist = opt->longs!=NULL && opt->longs[0]!='\0';
-
-	// short params
-	if(opt->shorts!=NULL && opt->shorts[0]!='\0'){
-		int len = strlen(opt->shorts);
-
-		for (int i=0; i<len-1; i++){
-			MY_SPRINTF("-%c, ", opt->shorts[i]);
-		}
-		
-		if(long_exist){
-			MY_SPRINTF("-%c, ", opt->shorts[len-1]);
-		}
-		else{
-			MY_SPRINTF("-%c", opt->shorts[len-1]);
-		}
-	}
-
-	if(long_exist){
-		if(opt->argRequirement==ARG_NONE)
-			MY_SPRINTF("--%s", opt->longs);
-		else if(opt->argRequirement==ARG_OPTIONAL)
-			MY_SPRINTF("--%s[=%s]", opt->longs, opt->argName);
-		else
-			MY_SPRINTF("--%s=%s", opt->longs, opt->argName);
-
-		
-	}
-
-	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->argRequirement!=ARG_NONE &&
-		(opt->argType!=ARG_STRING || opt->string!=NULL))
-	{
-		MY_SPRINTF("\n%*cdefault: %s=", char_max+1, ' ', opt->argName);
-		if(opt->argType>-4) // integer type
-			MY_SPRINTF("%ld",opt->integer);
-		else if(opt->argType>-8)
-			MY_SPRINTF("%g",opt->real);
-		else
-			MY_SPRINTF("%s",opt->string);
-	}
-
-	MY_SPRINTF("\n");
-}
-
-
-
-HXTStatus hxtOptProgGetHelp(HXTOptProgram* program, char text[16384])
-{
-	int offsetval = 0;
-	int* offset = &offsetval;
-	if(program->usage_line)
-		MY_SPRINTF("%s\n\n", program->usage_line);
-
-	if(program->start_description)
-		MY_SPRINTF("%s\n\n", program->start_description);
-
-	int oldOffset = *offset;
-	MY_SPRINTF("Application Options:\n");
-	int char_printed = *offset - oldOffset;
-
-	MY_SPRINTF("%.*s\n", char_printed>64?63:char_printed-1,
-   "---------------------------------------------------------------");
-
-	for (size_t i=0; i<program->opt_length; i++) {
-		printOptionLine(program->opts[i], text, offset);
-	}
-
-	if(program->end_description)
-		MY_SPRINTF("%s\n", program->end_description);
-	return HXT_STATUS_OK;
-}
\ No newline at end of file
diff --git a/contrib/hxt/hxt_option.h b/contrib/hxt/hxt_option.h
deleted file mode 100644
index c07e33e1cc..0000000000
--- a/contrib/hxt/hxt_option.h
+++ /dev/null
@@ -1,182 +0,0 @@
-#ifndef __HXT_OPT_H__
-#define __HXT_OPT_H__
-
-#include "hxt_tools.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct HXTOptListStruct HXTOptList;
-typedef struct HXTOptProgramStruct HXTOptProgram;
-
-/************** new option parsing method ******************
-
-  ## the program is detailed into a HXTOptProgram.
-  HXTOptProgram* program;
-  HXT_CHECK( hxtOptProgCreate(&program, 
-                "Usage: mon_programme [options]",                      ## a usage line for Help
-                "mon_programme is a programme that doesn't do much",   ## a description of the program
-                "Example:\n    mon_programme --coucou=David"           ## Examples, contact information etc.
-           ) );
-
-  ## then, we will add each possible options to this program
-  ## each options is detailed into a HXTOpt:
-  HXTOpt myOpt = {
-         "cC",     ## short option names (each character is a short name => '-c' and '-C' refer to this option)
-         "coucou", ## long option name   (a unique long name             => '--coucou' refers to this option)
-
-         "Prints coucou c to the screen\n" ## a description of this option
-         "Not usefull at all but funny",   ## can span multiple lines (no comma on the previous line)
-
-         coucouCallBack, ## a callback function called everytime the program is called
-                         ## the prototype of 'coucouCallBack' must be:
-                         ##     HXTStatus coucouCallBack(HXTOpt* opt, void* state);
-                         ## the option given will be 'myOpt'.
-                         ## the state is a pointer that we give to the parsing function
-
-         "YOUR_NAME",    ## the name of the argument to show in Help
-                         ## here Help will show: 
-                         ## -c, -C, --coucou=YOUR_NAME   Prints coucou YOUR_NAME to the screen
-
-         ARG_REQUIRED,   ## one of ARG_NONE, ARG_REQUIRED, ARG_OPTIONAL and ARG_NON_NULL_REQUIRED
-                         ## specify if an argument is required (see ARG_REQUIREMENT section)
-
-         ARG_STRING,     ## the type of the argument as described below (ARG_TYPE section)
-         
-         {.string="Joe"} ## a default value for the argument (uneeded here as the argument is required...)
-     };
-
-  ##then we add the option to the program:
-  HXT_CHECK( hxtOptProgAddOption(program, myOpt) );
-
-  ## Once all options are added, we can parse the argument.
-  ## The function will automatically return the status and print Help on errors
-
-  void* state = NULL;  ## this pointer will be given to each callback functions
-  int optind=0;        ## this integer will contain the number of string processed in argv
-  HXT_OPT_MAIN_PARSE(program, argc, argv, NULL, &optind );
-
-  ## you can now use the argument provided by the user safely
-  printf(" Coucou %s !!!", myOpt.string);
-
-  ## and delete the program structure
-  HXT_CHECK( hxtOptProgDelete(program) );
-
-*/
-
-
-/****************************************************************************************
- *  ARG_REQUIREMENT : specify if an argument is required to follow the option
- ***************************************************************************************/
-typedef enum {
-  ARG_NONE=0,     /* no argument, the union value is incremented at each call */
-  ARG_REQUIRED=1, /* argument required, the union value is the value of the argument */
-  ARG_OPTIONAL=2, /* optional argument, the union value is:
-                      - the value of the argument if there is an argument
-                      - INT64_MIN for integers type
-                      - NAN for floating point type if there was no argument
-                      - "\a" for string types
-                      */
-  ARG_NON_NULL_REQUIRED=3  /* argument is required and the option should be non-null
-                              at end of parsing */
-} ARG_REQUIREMENT;
-
-
-/****************************************************************************************
- *  ARG_TYPE: the accepted values of the possible argument
- * (use whatever you want if argRequirement==ARG_NONE)
- ***************************************************************************************/
-typedef enum {
-  // a positive value N means an integer between 0 and N included
-  ARG_POSITIVE_INT32=INT32_MAX,
-
-  /* Integer value types (stored in opt.integer) */
-  ARG_INT64=0,    // an integer, whatever fits in a int64_t
-  ARG_POSITIVE_INT64=-1,
-  ARG_INT32=-2, // the value is checked to fit in a int32_t
-  ARG_UINT32=-3,// the value is checked to fit in a uint32_t
-
-  /* Floating value types (stored in opt.real)   */
-  ARG_DOUBLE=-4,// a double value, whatever fits in a double
-  ARG_FLOAT=-5, // the value is checked to fit in a float
-  ARG_POSITIVE_FLOAT=-6, // the value is checked to fit in a float and be positive
-  ARG_POSITIVE_DOUBLE=-7,// the value is checked to fit in a double and be positive
-
-   /* String value type (stored in opt.string)    */
-  ARG_STRING=-8
-} ARG_TYPE;
-
-
-
-typedef struct HXTOptStruct{
-  const char* const shorts;
-  const char* const longs;
-  const char* const description;
-  HXTStatus (*const cb)(struct HXTOptStruct* arg, void* state);
-  const char* const argName;
-  const ARG_REQUIREMENT argRequirement;
-  const int argType;
-//  struct {
-    int64_t     integer;
-    double      real;
-    const char* string;
-//  }
-}HXTOpt;
-
-
-
-
-
-
-HXTStatus hxtOptProgCreate(HXTOptProgram** program_ptr,
-                           const char* usage_line,
-                           const char* start_description,
-                           const char* end_description);
-
-
-HXTStatus hxtOptProgAddOption(HXTOptProgram* program,
-                              HXTOpt* opt);
-
-
-HXTStatus hxtOptProgParse(HXTOptProgram* program,
-                          const int argc, char* argv[],
-                          void* state,
-                          int* optind);
-
-
-#define HXT_OPT_MAIN_PARSE(program, argc, argv, state, optind_ptr)               \
-  do {                                                                           \
-    char help[16384];                                                            \
-    hxtOptProgGetHelp(program, help);                                            \
-    HXTStatus _status = hxtOptProgParse(program, argc, argv, NULL, optind_ptr ); \
-    if(_status!=HXT_STATUS_OK){                                                  \
-      HXT_TRACE(_status);                                                        \
-      puts("\n  ==> Help on Error\n\n                              ---\n\n");    \
-      *optind_ptr=-1;                                                            \
-    }                                                                            \
-    if(*optind_ptr==-1) {                                                        \
-      printf("%s", help);                                                        \
-      HXT_CHECK( hxtOptProgDelete(program) );                                    \
-      return _status;                                                            \
-    }                                                                            \
-  }while(0)
-
-HXTStatus hxtOptCalledWithoutArg(HXTOpt* opt);
-
-HXTStatus hxtOptProgGetHelp(HXTOptProgram* program, char text[16384]);
-
-HXTStatus hxtOptProgDelete(HXTOptProgram* program);
-
-
-static inline HXTStatus hxtOptProgAddOptionArray(HXTOptProgram* program,
-                                                 HXTOpt* opt, int n) {
-  for (int i=0; i<n; i++) { HXT_CHECK( hxtOptProgAddOption(program, &opt[i]) ); }
-  return HXT_STATUS_OK;
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/contrib/hxt/hxt_parametrization.c b/contrib/hxt/hxt_parametrization.c
deleted file mode 100644
index 36d4a37920..0000000000
--- a/contrib/hxt/hxt_parametrization.c
+++ /dev/null
@@ -1,754 +0,0 @@
-#include "hxt_parametrization.h"
-#include "hxt_mean_values.h"
-#include "hxt_edge.h"
-#include "metis.h"
-
-
-/*
-
-// # O U T P U T
-
-int* colors; //gives colors of elements: colors[i] = color of i-th element
-int* nNodes; //gives  lower index of int* nodes for a color: nNodes[i] = first node index of i-th color
-int* nodes; //gives the global index of initial 'mesh': nodes[i] = if i=nNodes[c]+k, gives the global index of k-th node of c-th color
-double* uv; //give the uv param coordinates of a local node: uv[2*i+p] = u/v component of the global k-node of the c-th color
-
- */
-
-
-
-
-struct HXTVectorStruct{
-  void **ptr;
-  int last;
-  int length;
-};
-
-
-static HXTStatus hxtVectorInit(HXTVector **vecptr){
-
-
-  HXT_CHECK(hxtMalloc(vecptr,sizeof(HXTVector)));
-
-  HXTVector *new = *vecptr;
-
-  new->ptr = NULL;
-  new->last = -1;
-  new->length = 0;
-
-  return HXT_STATUS_OK;
-}
-
-
-static HXTStatus hxtVectorFree(HXTVector **vecptr){
-
-  HXTVector *vector = *vecptr;
-
-  HXT_CHECK(hxtFree(&vector->ptr));
-
-  HXT_CHECK(hxtFree(vecptr));
-
-  return HXT_STATUS_OK;
-
-}
-
-static HXTStatus hxtVectorPushBack(HXTVector *vector, void *object){
-
-  int i = vector->last;
-  int length = vector->length;
-
-  if(i+1 >= length){
-    if(length==0)
-      length=1;
-    HXT_CHECK(hxtRealloc(&vector->ptr,2*(length)*sizeof(void *)));
-    vector->length = 2*length;
-  }
-  vector->ptr[i+1] = object;
-  vector->last = i+1;
-
-  return HXT_STATUS_OK;
-}
-
-
-/*---------------------------------------*/
-
-
-
-struct HXTParametrizationStruct{
-  HXTEdges *edges;
-  int n;
-  HXTMeanValues **maps;
-};
-
-
-
-
-static HXTStatus hxtDoubleLongestEdge(HXTEdges *e, int tri, double *l)
-{
-  uint32_t *ed = &e->tri2edg[3*tri];
-  *l=0;
-
-  for(int i=0; i<3; i++){
-    uint64_t *tr= &e->edg2tri[2*ed[i]];
-
-    if(tr[1]==(uint64_t)-1)
-      continue;
-
-    if(*l<hxtEdgesLength(e,ed[i]))
-      *l=hxtEdgesLength(e,ed[i]);
-  }
-    return HXT_STATUS_OK;
-}
-
-static HXTStatus hxtLongestEdge(HXTEdges *edges, int tri,int *ie,int comp)
-{
-  uint32_t *ed = &edges->tri2edg[3*tri];
-  double longest = hxtEdgesLength(edges,comp);
-  *ie=comp;
-  for(int i=0; i<3; i++){
-    uint64_t *tr= &edges->edg2tri[2*ed[i]];
-
-    if(tr[1]==(uint64_t)-1)
-      continue;
-
-    if(longest<hxtEdgesLength(edges,ed[i])){
-      longest=hxtEdgesLength(edges,ed[i]);
-      *ie = ed[i];
-    }
-  }
-  return HXT_STATUS_OK;
-}
-
-static HXTStatus hxtLongestEdgeBisection(HXTEdges *edges,int nrefinements)
-{
-  double threshold = 0, counter=0;
-  for(uint32_t ie=0; ie<edges->numEdges; ie++)
-    if(edges->edg2tri[2*ie+1]==(uint64_t)-1){
-      threshold+= hxtEdgesLength(edges,ie);
-      counter++;
-    }
-  if (counter>0)
-    threshold/=counter;
-
-  // longest-edge bisection: boundary edges are not splitted
-  for(int ir=0; ir<nrefinements; ir++){
-    HXTEdges *e = edges;
-    HXTMesh *m = edges->edg2mesh;
-
-
-
-    uint64_t *flag=NULL;
-    HXT_CHECK(hxtMalloc(&flag,m->triangles.num*sizeof(uint64_t)));
-    for(uint64_t it=0; it<m->triangles.num; it++){
-      double l;
-      HXT_CHECK(hxtDoubleLongestEdge(e,it,&l));
-      if(l>2*threshold)
-        flag[it] = 0;
-      else
-        flag[it] = 1;
-    }
-
-    int maxVert = m->vertices.num;
-    int maxTri = m->triangles.num;
-    int maxEdg = e->numEdges;
-    uint64_t initialNumberOfTriangles = m->triangles.num;
-    for(uint64_t it=0; it<initialNumberOfTriangles; it++){
-      if(flag[it] > 0)
-        continue;
-
-      while(flag[it]==0){
-        int ti = (int) it, tj;
-        int ei,ej;
-        for(int ib=0; ib<3; ib++){
-          if (e->edg2tri[2*e->tri2edg[3*it+ib]+1] == (uint64_t) -1)
-            continue;
-          else{
-            hxtLongestEdge(e,it,&ej,e->tri2edg[3*it+ib]);
-            break;
-          }
-        }
-        do{
-          HXT_CHECK(hxtLongestEdge(e,ti,&ei,ej));
-          tj = e->edg2tri[2*ei+0]==ti ? e->edg2tri[2*ei+1] : e->edg2tri[2*ei+0];
-          HXT_CHECK(hxtLongestEdge(e,tj,&ej,ei));
-          ti =  e->edg2tri[2*ej+0]==tj ? e->edg2tri[2*ej+1] : e->edg2tri[2*ej+0];
-        }while(ei!=ej);
-
-        m->vertices.num += 1;
-        if(m->vertices.num > maxVert){
-          maxVert *= 2;
-          HXT_CHECK(hxtAlignedRealloc(&m->vertices.coord,4*maxVert*sizeof(double)));
-        }
-        int ni = e->node[2*ei+0], nj = e->node[2*ei+1];
-
-        for(int xj=0; xj<3; xj++)
-          m->vertices.coord[4*(m->vertices.num-1)+xj] = ( m->vertices.coord[4*ni+xj] + m->vertices.coord[4*nj+xj] )/2.;
-
-        m->triangles.num +=2;
-        if(m->triangles.num > maxTri){
-          maxTri *= 2;
-          HXT_CHECK(hxtAlignedRealloc(&m->triangles.node,3*maxTri*sizeof(uint32_t)));
-          HXT_CHECK(hxtAlignedRealloc(&m->triangles.colors,maxTri*sizeof(uint16_t)));
-          HXT_CHECK(hxtRealloc(&e->tri2edg,3*maxTri*sizeof(uint32_t)));
-        }
-        int tti = m->triangles.num-2, ttj = tti+1;
-        int e0 = e->numEdges, e1=e0+1, e2=e1+1;
-        for(int ic=0; ic<3; ic++){
-          if(m->triangles.node[3*ti+ic]==ni && m->triangles.node[3*ti+(ic+1)%3]==nj){
-            m->triangles.node[3*ti+(ic+1)%3] = m->vertices.num-1;
-
-            m->triangles.node[3*tti+0] = m->vertices.num-1;
-            m->triangles.node[3*tti+1] = nj;
-            m->triangles.node[3*tti+2] = m->triangles.node[3*ti+(ic+2)%3];
-            e->tri2edg[3*tti+0] = e0;
-            e->tri2edg[3*tti+1] = e->tri2edg[3*ti+(ic+1)%3];
-            e->tri2edg[3*tti+2] = e1;
-
-            e->tri2edg[3*ti+(ic+1)%3] = e1;
-
-            uint64_t *t_ = &e->edg2tri[2*e->tri2edg[3*tti+1]];
-            if(t_[0]==ti)
-              t_[0] = tti;
-            else
-              t_[1] = tti;
-
-          }
-          else if (m->triangles.node[3*ti+ic]==nj && m->triangles.node[3*ti+(ic+1)%3]==ni) {
-            m->triangles.node[3*ti+ic] = m->vertices.num-1;
-
-            m->triangles.node[3*tti+0] = nj;
-            m->triangles.node[3*tti+1] = m->vertices.num-1;
-            m->triangles.node[3*tti+2] = m->triangles.node[3*ti+(ic+2)%3];
-            e->tri2edg[3*tti+0] = e0;
-            e->tri2edg[3*tti+1] = e1;
-            e->tri2edg[3*tti+2] = e->tri2edg[3*ti+(ic+2)%3];
-
-            e->tri2edg[3*ti+(ic+2)%3] = e1;
-
-
-            uint64_t *t_ = &e->edg2tri[2*e->tri2edg[3*tti+2]];
-            if(t_[0]==ti)
-              t_[0] = tti;
-            else
-              t_[1] = tti;
-
-          }
-          if(m->triangles.node[3*tj+ic]==nj && m->triangles.node[3*tj+(ic+1)%3]==ni){
-            m->triangles.node[3*tj+(ic+1)%3] = m->vertices.num-1;
-
-            m->triangles.node[3*ttj+0] = m->vertices.num-1;
-            m->triangles.node[3*ttj+1] = ni;
-            m->triangles.node[3*ttj+2] = m->triangles.node[3*tj+(ic+2)%3];
-            e->tri2edg[3*ttj+0] = ei;
-            e->tri2edg[3*ttj+1] = e->tri2edg[3*tj+(ic+1)%3];
-            e->tri2edg[3*ttj+2] = e2;
-
-            e->tri2edg[3*tj+(ic+1)%3] = e2;
-            e->tri2edg[3*tj+ic] = e0;
-
-            uint64_t *t_ = &e->edg2tri[2*e->tri2edg[3*ttj+1]];
-            if(t_[0]==tj)
-              t_[0] = ttj;
-            else
-              t_[1] = ttj;
-
-
-          }
-          else if (m->triangles.node[3*tj+ic]==ni && m->triangles.node[3*tj+(ic+1)%3]==nj){
-
-            m->triangles.node[3*tj+ic] = m->vertices.num-1;
-
-            m->triangles.node[3*ttj+0] = ni;
-            m->triangles.node[3*ttj+1] = m->vertices.num-1;
-            m->triangles.node[3*ttj+2] = m->triangles.node[3*tj+(ic+2)%3];
-            e->tri2edg[3*ttj+0] = ei;
-            e->tri2edg[3*ttj+1] = e2;
-            e->tri2edg[3*ttj+2] = e->tri2edg[3*tj+(ic+2)%3];
-
-            e->tri2edg[3*tj+ic] = e0;
-            e->tri2edg[3*tj+(ic+2)%3] = e2;
-
-            uint64_t *t_ = &e->edg2tri[2*e->tri2edg[3*ttj+2]];
-            if(t_[0]==tj)
-              t_[0] = ttj;
-            else
-              t_[1] = ttj;
-
-          }
-        }//end for
-        e->numEdges +=3;
-        if(e->numEdges > maxEdg){
-          maxEdg *= 2;
-          HXT_CHECK(hxtRealloc(&e->node,2*maxEdg*sizeof(uint32_t)));
-          HXT_CHECK(hxtRealloc(&e->color,maxEdg*sizeof(uint16_t)));
-          HXT_CHECK(hxtRealloc(&e->edg2tri,2*maxEdg*sizeof(uint64_t)));
-        }
-        e->node[2*ei+1] = m->vertices.num-1;
-        e->edg2tri[2*ei+0] = ti;
-        e->edg2tri[2*ei+1] = ttj;
-        e->node[2*e0+0] = m->vertices.num-1;
-        e->node[2*e0+1] = nj;
-        e->edg2tri[2*e0+0] = tti;
-        e->edg2tri[2*e0+1] = tj;
-        e->node[2*e1+0] = m->vertices.num-1;
-        e->node[2*e1+1] = m->triangles.node[3*tti+2];
-        e->edg2tri[2*e1+0] = ti;
-        e->edg2tri[2*e1+1] = tti;
-        e->node[2*e2+0] = m->vertices.num-1;
-        e->node[2*e2+1] = m->triangles.node[3*ttj+2];
-        e->edg2tri[2*e2+0] = tj;
-        e->edg2tri[2*e2+1] = ttj;
-
-
-        if (ti < initialNumberOfTriangles)
-          flag[ti] = 1;
-        if (tj < initialNumberOfTriangles)
-          flag[tj] = 1;
-
-      }// end while flag[it]==0
-    }//end for it
-
-    if(threshold>0)
-      for(uint64_t it=0; it<m->triangles.num; it++){
-        double l;
-        HXT_CHECK(hxtDoubleLongestEdge(e,it,&l));
-        if(l>2*threshold && nrefinements<10){
-          nrefinements++;
-          break;
-        }
-      }
-
-
-  }//end refinement
-
-
-
-
-  return HXT_STATUS_OK;
-}
-
-static HXTStatus hxtPartitioning(HXTEdges *edges,int *part, int nPartitions,HXTVector *partitions)
-{
-
-  HXTMesh *mesh = edges->edg2mesh;
-
-  uint32_t *flagVertices;
-  HXT_CHECK(hxtMalloc(&flagVertices,mesh->vertices.num*sizeof(uint32_t)));
-  for(int p = 0; p<nPartitions; p++){
-    HXTMesh *msh=NULL;
-    HXT_CHECK(hxtMeshCreate(mesh->ctx,&msh));
-
-
-    for(uint32_t iv=0; iv<mesh->vertices.num; iv++)
-      flagVertices[iv] = -1;
-
-    uint32_t cv = 0;
-    uint64_t ce = 0;
-    for(uint64_t ie=0; ie<mesh->triangles.num; ie++){
-      if(part[ie]==p){
-        for(int jv=0; jv<3; jv++){
-          uint32_t current = mesh->triangles.node[3*ie+jv];
-          if(flagVertices[current] == (uint32_t)-1)
-            flagVertices[current] = cv++;
-        }
-        ce++;
-      }
-    }
-    /*
-      printf("------------stat \t part %d---------------\n",p);
-      printf("\t number of vertices:%u\n",cv);
-      printf("\t number of elements:%lu\n",ce);
-    */
-    msh->vertices.num = cv;
-    HXT_CHECK(hxtAlignedMalloc(&msh->vertices.coord,4*cv*sizeof(double)));
-    for(uint32_t iv=0; iv<mesh->vertices.num; iv++){
-      uint32_t current = flagVertices[iv];
-      if(current==(uint32_t)-1);
-      else{
-        msh->vertices.coord[4*current+0] = mesh->vertices.coord[4*iv+0];
-        msh->vertices.coord[4*current+1] = mesh->vertices.coord[4*iv+1];
-        msh->vertices.coord[4*current+2] = mesh->vertices.coord[4*iv+2];
-        msh->vertices.coord[4*current+3] = mesh->vertices.coord[4*iv+3];
-      }
-    }
-
-    msh->triangles.num = ce;
-    //<
-    uint64_t *global;
-    HXT_CHECK(hxtMalloc(&global,ce*sizeof(uint64_t)));
-    //>
-    HXT_CHECK( hxtAlignedMalloc(&msh->triangles.node,ce*3*sizeof(uint32_t)) );
-    HXT_CHECK( hxtAlignedMalloc(&msh->triangles.colors,ce*sizeof(uint16_t)) );
-    ce = 0;
-    for(uint64_t ie=0; ie<mesh->triangles.num; ie++){
-      if(part[ie]==p){
-        global[ce] = edges->global[ie];
-        msh->triangles.colors[ce] = mesh->triangles.colors[ie];
-        for(int jv=0; jv<3; jv++){
-          uint32_t current = flagVertices[mesh->triangles.node[3*ie+jv]];
-          msh->triangles.node[3*ce+jv] = current;
-        }
-        ce++;
-      }
-    }
-    HXTEdges* edg = NULL;
-    HXT_CHECK(hxtEdgesCreate(msh,&edg));
-    edg->global = global;
-    HXT_CHECK(hxtVectorPushBack(partitions,edg));
-  }
-
-  return HXT_STATUS_OK;
-
-}
-
-static HXTStatus hxtCheckConnectivity(HXTEdges *e,HXTVector *partitions)
-{
-
-  HXTMesh *m = e->edg2mesh;
-
-  int *flag = NULL;
-  HXT_CHECK(hxtMalloc(&flag,m->triangles.num*sizeof(int)));
-  for(uint64_t i=0; i<m->triangles.num; i++)
-    flag[i] = -1;
-
-  uint64_t *queue = NULL;
-  HXT_CHECK(hxtMalloc(&queue,m->triangles.num*sizeof(uint64_t)));
-  int last = 1;
-
-
-  uint64_t *idx = NULL;
-  HXT_CHECK(hxtMalloc(&idx,(m->triangles.num+1)*sizeof(uint64_t)));
-
-
-  int count = 0;
-  flag[0] = count;
-  queue[0] = 0;
-  int goOn = 1;
-  int iq=0;
-  idx[0] = 1;
-  while(goOn){
-    for(; iq<last; iq++){
-      idx[iq+1] = idx[iq];
-      uint64_t current = queue[iq];
-      uint32_t *ed = &e->tri2edg[3*current];
-      for(int j=0; j<3; j++){
-        if (e->edg2tri[2*ed[j]+1] == (uint64_t) -1)
-          continue;
-        uint64_t next = e->edg2tri[2*ed[j]] == current ? e->edg2tri[2*ed[j]+1] : e->edg2tri[2*ed[j]];
-        if (flag[next] == -1){
-          queue[last]= next;
-          last++;
-          idx[iq+1]++;
-          flag[next] = (int) count;
-        }
-      }
-    }
-    count++;
-    goOn = 0;
-    for(uint64_t i=0; i<m->triangles.num; i++)
-      if (flag[i]== -1){
-        goOn=1;
-        iq=last;
-        queue[last] = i;
-        last++;
-        flag[i] = count;
-        break;
-      }
-  }
-
-  //  printf("HXT_INFO \t There is/are %d connected part(s).\n",count);
-
-  for(uint64_t i=0; i<m->triangles.num; i++){
-    uint32_t *refVert = &m->triangles.node[3*queue[i]];
-    for(uint64_t j=idx[i]+flag[queue[i]]; j<idx[i+1]+flag[queue[i]]; j++){
-
-      int cond = 0;
-      uint32_t *checkVert = &m->triangles.node[3*queue[j]];
-      for(int ii=0; ii<3; ii++){
-        for(int jj=0; jj<3; jj++){
-          if(refVert[ii]==checkVert[(jj+1)%3] && refVert[(ii+1)%3]==checkVert[jj]){
-            cond = 1;
-            break;
-          }
-        }
-        if(cond==1)
-          break;
-      }//end for ii
-      if(cond==0){
-        printf("Unconsistent orientation \t %lu (%u %u %u) ; (%u %u)-(%u %u)-(%u %u) [%d] ~ %lu (%u %u %u) ; (%u %u)-(%u %u)-(%u %u) [%d].\n",queue[i],refVert[0],refVert[1],refVert[2],e->node[2*e->tri2edg[3*queue[i]+0]+0],e->node[2*e->tri2edg[3*queue[i]+0]+1],e->node[2*e->tri2edg[3*queue[i]+1]+0],e->node[2*e->tri2edg[3*queue[i]+1]+1],e->node[2*e->tri2edg[3*queue[i]+2]+0],e->node[2*e->tri2edg[3*queue[i]+2]+1],flag[queue[i]],queue[j],checkVert[0],checkVert[1],checkVert[2],e->node[2*e->tri2edg[3*queue[j]+0]+0],e->node[2*e->tri2edg[3*queue[j]+0]+1],e->node[2*e->tri2edg[3*queue[j]+1]+0],e->node[2*e->tri2edg[3*queue[j]+1]+1],e->node[2*e->tri2edg[3*queue[j]+2]+0],e->node[2*e->tri2edg[3*queue[j]+2]+1],flag[queue[j]]);
-        uint64_t temp = m->triangles.node[3*queue[j]+0];
-        m->triangles.node[3*queue[j]+0] = m->triangles.node[3*queue[j]+1];
-        m->triangles.node[3*queue[j]+1] = temp;
-        uint32_t te = e->tri2edg[3*queue[j]+1];
-        e->tri2edg[3*queue[j]+1] = e->tri2edg[3*queue[j]+2];
-        e->tri2edg[3*queue[j]+2] = te;
-
-        printf("Consistent (?) orientation \t %lu (%u %u %u) ; (%u %u)-(%u %u)-(%u %u) [%d] ~ %lu (%u %u %u) ; (%u %u)-(%u %u)-(%u %u) [%d].\n",queue[i],refVert[0],refVert[1],refVert[2],e->node[2*e->tri2edg[3*queue[i]+0]+0],e->node[2*e->tri2edg[3*queue[i]+0]+1],e->node[2*e->tri2edg[3*queue[i]+1]+0],e->node[2*e->tri2edg[3*queue[i]+1]+1],e->node[2*e->tri2edg[3*queue[i]+2]+0],e->node[2*e->tri2edg[3*queue[i]+2]+1],flag[queue[i]],queue[j],checkVert[0],checkVert[1],checkVert[2],e->node[2*e->tri2edg[3*queue[j]+0]+0],e->node[2*e->tri2edg[3*queue[j]+0]+1],e->node[2*e->tri2edg[3*queue[j]+1]+0],e->node[2*e->tri2edg[3*queue[j]+1]+1],e->node[2*e->tri2edg[3*queue[j]+2]+0],e->node[2*e->tri2edg[3*queue[j]+2]+1],flag[queue[j]]);
-
-      }//end if cond==0
-    }//end for j
-  }//end for i
-
-  if (partitions!=NULL)
-    HXT_CHECK(hxtPartitioning(e,(int*)flag,count,partitions));
-
-  return HXT_STATUS_OK;
-}
-
-
-static HXTStatus hxtSplitEdges(HXTEdges *edges,int nPartitions,HXTVector *partitions)
-{
-
-  HXTMesh *mesh = edges->edg2mesh;
-
-  uint32_t *tri2edg = edges->tri2edg;
-  uint64_t *edg2tri = edges->edg2tri;
-
-  HXTBoundaries *boundaries;
-  HXT_CHECK(hxtEdgesSetBoundaries(edges, &boundaries));
-  int nbedg;
-  HXT_CHECK(hxtBoundariesGetNumberOfBorderEdges(boundaries,&nbedg));
-
-  int nVertex = (int) mesh->triangles.num;
-  int nEdge = (int) (edges->numEdges) - nbedg;
-
-  int *idx=NULL;
-  HXT_CHECK(hxtMalloc(&idx,(nVertex+1)*sizeof(int)));
-  int *nbh=NULL;
-  HXT_CHECK(hxtMalloc(&nbh, 2*nEdge*sizeof(int)));
-  int *weights=NULL;
-  HXT_CHECK(hxtMalloc(&weights,2*nEdge*sizeof(int)));
-
-  idx[0] = 0;
-  for(int i=0; i<nVertex; i++){// triangle by triangle
-    uint32_t *current = &tri2edg[3*i];
-    int temp = 0;
-    for(int j=0; j<3; j++){
-      uint64_t *local = &edg2tri[2*current[j]];
-      if(local[1]==(uint64_t)-1)
-        continue;
-      else{
-        nbh[idx[i]+temp] = i == (int) local[0] ? (int) local[1] : (int) local[0];
-        weights[idx[i]+temp] = (int) (hxtEdgesLength(edges,current[j])+1);
-        temp++;
-      }
-    }
-
-    idx[i+1] = idx[i] + temp;
-  }
-
-
-  // only for k-way
-  idx_t options[METIS_NOPTIONS];
-  METIS_SetDefaultOptions(options);
-  options[METIS_OPTION_NCUTS] = nPartitions;
-  //options[METIS_OPTION_MINCONN] = 1;
-  //options[METIS_OPTION_CCORDER] = 1;
-  options[METIS_OPTION_CONTIG] = 1;
-  //options[METIS_OPTION_DBGLVL] = 1;
-
-  int edgeCut;
-  int *part;
-  HXT_CHECK(hxtMalloc(&part,nVertex*sizeof(int)));
-  //int zero = 0;
-  int one=1;
-  //METIS_PartGraphRecursive(&nVertex,&one,idx,nbh,NULL,NULL,NULL,&nPartitions,NULL,NULL,NULL,&edgeCut,part);
-  METIS_PartGraphKway(&nVertex,&one,idx,nbh,NULL,NULL,weights,&nPartitions,NULL,NULL,options,&edgeCut,part);
-
-  HXT_CHECK(hxtFree(&nbh));
-  HXT_CHECK(hxtFree(&idx));
-
-  HXT_CHECK(hxtPartitioning(edges,part,nPartitions,partitions));
-
-  return HXT_STATUS_OK;
-}
-
-static HXTStatus hxtCuttingProcess(HXTEdges *edges, int ar, int bool, HXTVector *toparam)
-{
-  HXTBoundaries *boundaries;
-  HXT_CHECK(hxtEdgesSetBoundaries(edges, &boundaries));
-  int nll, seamPoint;
-  HXT_CHECK(hxtBoundariesGetNumberOfLineLoops(boundaries,&nll));
-  int g = (edges->numEdges - edges->edg2mesh->vertices.num - edges->edg2mesh->triangles.num + 2 - nll)/2;
-  HXT_CHECK(hxtBoundariesGetSeamPoint(boundaries,&seamPoint));
-
-  HXTVector *toSplit;
-  HXT_CHECK(hxtVectorInit(&toSplit));
-  if(seamPoint!=0 || ar==0 || g!=0 || nll == 0)
-    HXT_CHECK(hxtVectorPushBack(toSplit,edges));
-  else
-    HXT_CHECK(hxtVectorPushBack(toparam,edges));
-  for(int i=0; i<toSplit->last+1; i++){
-    HXTVector *split=NULL;
-    HXT_CHECK(hxtVectorInit(&split));
-    HXTEdges *beingSplitted = (HXTEdges*) toSplit->ptr[i];
-    HXT_CHECK(hxtSplitEdges(beingSplitted,2,split));
-    if(bool>0){
-      HXT_CHECK(hxtMeshDelete(&beingSplitted->edg2mesh));
-      HXT_CHECK(hxtEdgesDelete(&beingSplitted));
-    }
-    else
-      bool=1;
-    for(int j=0; j<split->last+1; j++){
-      HXTEdges* piece = (HXTEdges*) split->ptr[j];
-      HXT_CHECK(hxtEdgesSetBoundaries(piece, &boundaries));
-      HXT_CHECK(hxtBoundariesGetNumberOfLineLoops(boundaries,&nll));
-      g = (piece->numEdges - piece->edg2mesh->vertices.num  - piece->edg2mesh->triangles.num + 2 - nll)/2;
-      HXT_CHECK(hxtBoundariesGetSeamPoint(boundaries,&seamPoint));
-      if(seamPoint !=0 || g != 0 || nll == 0){
-        //printf("nl=%d\t g=%d\n",nll,g);
-        HXT_CHECK(hxtVectorPushBack(toSplit,piece));
-      }
-      else
-        HXT_CHECK(hxtVectorPushBack(toparam,piece));
-    }
-    HXT_CHECK(hxtVectorFree(&split));
-  }
-  HXT_CHECK(hxtVectorFree(&toSplit));
-  // free boundaries
-
-  return HXT_STATUS_OK;
-}
-
-HXTStatus hxtParametrizationCreate(HXTMesh *mesh, int nrefinements, HXTParametrization **parametrization)
-{
-  HXTParametrization* param0;
-  HXT_CHECK(hxtMalloc(&param0,sizeof(HXTParametrization)));
-  *parametrization = param0;
-
-  HXTMesh *initialMesh=NULL;
-  HXT_CHECK(hxtMeshCreate(mesh->ctx,&initialMesh));
-  *initialMesh = *mesh;
-  HXT_CHECK(hxtEdgesCreate(initialMesh, &param0->edges));
-
-  //  printf("checking connectivity ...\n");
-  HXT_CHECK(hxtCheckConnectivity(param0->edges,NULL));
-  //  HXT_CHECK(hxtLongestEdgeBisection(param0->edges,nrefinements));
-
-  HXTEdges *edges=NULL;
-  HXT_CHECK(hxtEdgesCreate(initialMesh, &edges));
-  uint64_t *global;
-  HXT_CHECK(hxtMalloc(&global,edges->edg2mesh->triangles.num*sizeof(uint64_t)));
-  for(uint64_t i=0; i<edges->edg2mesh->triangles.num; i++)
-    global[i]= i;
-  edges->global = global;
-  param0->edges->global = global;
-
-  HXTVector *connect;
-  HXT_CHECK(hxtVectorInit(&connect));
-  HXT_CHECK(hxtCheckConnectivity(edges,connect));
-
-  //  printf("connectivity is done\n");
-
-  HXTVector *toparam;
-  HXT_CHECK(hxtVectorInit(&toparam));
-  for(int i=0; i<connect->last+1; i++){
-    HXT_CHECK(hxtCuttingProcess(connect->ptr[i],1,0,toparam));
-  }
-  //printf("initial cutting process is done, %d\n",  param0->n);
-  //  return HXT_STATUS_OK;
-
-
-  HXTVector *atlas;
-  HXT_CHECK(hxtVectorInit(&atlas));
-  for(int i=0; i<toparam->last+1; i++){
-    HXTMeanValues *param;
-    HXTEdges *current = (HXTEdges *)(toparam->ptr[i]);
-    HXT_CHECK(hxtMeanValuesCreate(current,&param));
-    HXT_CHECK(hxtMeanValuesCompute(param));
-    int ar = 0;
-    HXT_CHECK(hxtMeanValueAspectRatio(param,&ar));
-
-    if (0 && ar==0)
-      HXT_CHECK(hxtCuttingProcess(current,ar,toparam->last,toparam));
-    else
-      HXT_CHECK(hxtVectorPushBack(atlas,param));
-  }
-  hxtVectorFree(&toparam);
-
-  param0->n = atlas->last+1;
-  HXT_CHECK(hxtMalloc(&param0->maps,param0->n*sizeof(HXTMeanValues*)));
-  for(int i=0; i<param0->n; i++)
-    param0->maps[i] = (HXTMeanValues *) atlas->ptr[i];
-
-  HXT_CHECK(hxtVectorFree(&atlas));
-  return HXT_STATUS_OK;
-}
-
-
-
-HXTStatus hxtParametrizationDelete(HXTParametrization **parametrization)
-{
-
-  return HXT_STATUS_OK;
-}
-
-HXTStatus hxtParametrizationCompute(HXTParametrization *parametrization, int **_colors_, int **_nNodes_, int **_nodes_, double **_uv_, int *nc, HXTMesh **m)
-{
-
-  int *colors=NULL, *nNodes=NULL, *nodes=NULL;
-  double *uv=NULL;
-
-  *m = parametrization->edges->edg2mesh;
-  int Ncolors = parametrization->n;
-  *nc=Ncolors;
-  int totalNtriangles = (int) parametrization->edges->edg2mesh->triangles.num;
-  HXT_CHECK(hxtMalloc(&colors,totalNtriangles*sizeof(int)));
-  HXT_CHECK(hxtMalloc(&nNodes,(Ncolors+1)*sizeof(int)));
-  nNodes[0] = 0;
-  for(int c=0; c<Ncolors; c++){
-
-    uint64_t *global=NULL;
-    int nv, ne;
-    HXT_CHECK(hxtMeanValuesGetData(parametrization->maps[c],&global, NULL, NULL, &nv,&ne,0));
-    nNodes[c+1] = nNodes[c]+nv;
-
-    for(int ie=0; ie<ne; ie++)
-      colors[global[ie]] = c;
-
-    HXT_CHECK(hxtFree(&global));
-
-  }
-
-
-  HXT_CHECK(hxtMalloc(&uv,2*nNodes[Ncolors]*sizeof(double)));//
-  HXT_CHECK(hxtMalloc(&nodes,nNodes[Ncolors]*sizeof(int)));
-  for(int it=0; it<nNodes[Ncolors]; it++)
-    nodes[it] = -1;
-
-  for(int c=0; c<Ncolors; c++){
-
-    uint64_t *global=NULL;
-    uint32_t *gn=NULL;
-    double *uvc=NULL;
-    int nv, ne;
-    HXT_CHECK(hxtMeanValuesGetData(parametrization->maps[c],&global, &gn, &uvc, &nv,&ne,0));
-    for(int iv=0; iv<2*nv; iv++)
-      uv[2*nNodes[c]+iv] = uvc[iv];
-
-    for(int ie=0; ie<ne; ie++){
-      for(int kk=0; kk<3; kk++){
-        int gvn = (int) parametrization->edges->edg2mesh->triangles.node[3*global[ie]+kk];
-        nodes[nNodes[c]+gn[3*ie+kk]] = gvn;
-      }
-    }
-
-    HXT_CHECK(hxtFree(&global));
-    HXT_CHECK(hxtFree(&gn));
-    HXT_CHECK(hxtFree(&uvc));
-  }
-
-
-  *_colors_=colors;
-  *_nNodes_=nNodes;
-  *_nodes_=nodes;
-  *_uv_=uv;
-
-  return HXT_STATUS_OK;
-}
-
-HXTStatus hxtParametrizationWrite(HXTParametrization *parametrization, const char *filename)
-{
-
-  return HXT_STATUS_OK;
-}
diff --git a/contrib/hxt/hxt_parametrization.h b/contrib/hxt/hxt_parametrization.h
deleted file mode 100644
index 3943041aad..0000000000
--- a/contrib/hxt/hxt_parametrization.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef HEXTREME_PARAMETRIZATION_H
-#define HEXTREME_PARAMETRIZATION_H
-
-#include "hxt_tools.h"
-#include "hxt_mesh.h"
-#include "hxt_edge.h"
-
-typedef struct HXTVectorStruct HXTVector;
-typedef struct HXTParametrizationStruct HXTParametrization;
-
-HXTStatus hxtParametrizationCreate(HXTMesh *mesh, int nrefinements, HXTParametrization **parametrization);
-HXTStatus hxtParametrizationDelete(HXTParametrization **parametrization);
-HXTStatus hxtParametrizationCompute(HXTParametrization *parametrization, int **colors, int **nNodes, int **nodes, double **uv, int*nc, HXTMesh **m);
-HXTStatus hxtParametrizationWrite(HXTParametrization *parametrization, const char *filename);
-
-
-#endif
diff --git a/contrib/hxt/hxt_tetOpti.c b/contrib/hxt/hxt_tetOpti.c
deleted file mode 100644
index 95bd189515..0000000000
--- a/contrib/hxt/hxt_tetOpti.c
+++ /dev/null
@@ -1,819 +0,0 @@
-#include "hxt_tetOpti.h"
-#include "hxt_tetFlag.h"
-#include "hxt_edgeRemoval.h"
-#include "hxt_smoothing.h"
-#include "hxt_sort.h"
-#include "HXTSPR.h"
-#include "hxt_tetRepair.h"
-#include "hxt_tetOptiDate.h"
-
-#define SMALLEST_ROUND 1024
-
-/**************************************************************************
-                    Thread-shared structure
- **************************************************************************/
-typedef struct {
-  struct {
-    HXTGroup2* array;
-    uint64_t num;
-    uint64_t size;
-  } badTets;
-
-  HXTTetDates date;
-  HXTTetQualities quality;
-  HXT2Sync toSync;
-
-  int numThreads;
-  uint32_t seed;
-} ThreadShared;
-
-
-/* Statistics about the mesh improvement.
- * Attempts and conflicts are per operation, so for smoothing and
- * edge-removal, there can be up to 6 E-R attempts and 4 Smoothing attempts
- * = 10 attempts (and maybe also conflict) per bad tetrahedra.
- * Success and failure are per bad tet.
- * Note that the number of `bad tet != failure + success`
- * because some bad tet gets eliminated by operations on other bad tets.
- * Also, some tets might cross partition boundary, in which case conflict
- * is guaranteed, therefore no operation are attempted and the tet does not
- * count in either success or failure */
-typedef struct {
-  uint64_t attempt;
-  uint64_t conflict;
-  uint64_t success; // cavity was modified, but there may still be a bad tet.
-  uint64_t failure;
-} Statistic;
-
-
-typedef struct 
-{
-  // cavity for edge removal is a bipyramid
-  HXTEdgeRemovalData* edgeRemoval;
-  HXTSmoothingData* smoothing;
-  HXTSPRData* SPR;
-
-  // list of deleted tet. Added when the cavity is created, removed when the cavity is filled
-  HXTDeleted deleted;
-  HXTPartition partition;
-  Statistic stat;
-} ThreadLocal;
-
-
-static void qualitySetDeleted(void** qualityArray_ptr, uint64_t a, uint64_t b)
-{
-  double* qualityArray = *qualityArray_ptr;
-
-  for (uint64_t i=a; i<b; i++) {
-    qualityArray[i] = DBL_MAX;
-  }
-}
-
-
-
-/**************************************************************************
-  create/update/delete shared structure, containing list of bad tetrahedra
- **************************************************************************/
-
-// suppose that the right capacity for quality values is already allocated
-static HXTStatus threadShared_update(HXTMesh* mesh, ThreadShared* shared) {
-  int maxThreads = omp_get_max_threads();
-  HXTStatus status = HXT_STATUS_OK;
-
-  uint64_t* badTetsCount;
-  HXT_CHECK( hxtMalloc(&badTetsCount, maxThreads*sizeof(uint64_t)) );
-
-#ifndef __SANITIZE_ADDRESS__ // this portion does not seem to work with the address sanitizer of GCC 8 with OpenMP
-  #pragma omp parallel
-#endif
-  {
-    int threadID = omp_get_thread_num();
-    badTetsCount[threadID] = 0;
-
-    #pragma omp for schedule(static)
-    for (uint64_t i=0; i<mesh->tetrahedra.num; i++) {
-      if(!getProcessedFlag(mesh, i) && !getDeletedFlag(mesh, i) && shared->quality.values[i]<shared->quality.threshold)
-        badTetsCount[threadID]++;
-    }
-
-    #pragma omp barrier
-    #pragma omp single
-    {
-      int nthreads = omp_get_num_threads();
-      shared->badTets.num = 0;
-      for (int i=0; i<nthreads; i++) {
-        uint64_t tsum = badTetsCount[i] + shared->badTets.num;
-        badTetsCount[i] = shared->badTets.num;
-        shared->badTets.num = tsum;
-      }
-
-      if(shared->badTets.num > shared->badTets.size) {
-        hxtAlignedFree(&shared->badTets.array);
-        hxtAlignedMalloc(&shared->badTets.array, sizeof(HXTGroup2)*shared->badTets.num);
-        shared->badTets.size = shared->badTets.num;
-      }
-    }
-
-    if(status==HXT_STATUS_OK){
-      #pragma omp for schedule(static)
-      for (uint64_t i=0; i<mesh->tetrahedra.num; i++) {
-        if(!getProcessedFlag(mesh, i) && !getDeletedFlag(mesh, i) && shared->quality.values[i]<shared->quality.threshold){
-          uint64_t badTetsID = badTetsCount[threadID]++;
-          shared->badTets.array[badTetsID].v[1] = i;
-        }
-      }
-    }
-  }
-  HXT_CHECK( hxtFree(&badTetsCount) );
-
-  shared->toSync.threadFinished = 0;
-
-  return status;
-}
-
-static HXTStatus threadShared_create(HXTMesh *mesh,
-                                     HXTOptimizeOptions* options,
-                                     ThreadShared** shared) {
-  ThreadShared* newShared;
-  HXT_CHECK( hxtMalloc(&newShared, sizeof(ThreadShared)));
-  newShared->numThreads = options->numThreads;
-
-  if(options->qualityMin<0.0)
-    return HXT_ERROR_MSG(HXT_STATUS_ERROR, "quality threshold must be positive");
-
-  newShared->badTets.array = NULL;
-  newShared->badTets.size = 0;
-  newShared->badTets.num = 0;
-  newShared->quality.function = options->qualityFun ? options->qualityFun : hxtTetAspectRatio;
-  newShared->quality.threshold = options->qualityMin;
-  newShared->quality.userData = options->qualityData;
-  HXT_CHECK( hxtAlignedMalloc(&newShared->quality.values, sizeof(double)*mesh->tetrahedra.size) );
-
-  newShared->date.current = 0;
-  HXT_CHECK( hxtAlignedMalloc(&newShared->date.values, sizeof(HXTTetDate)*mesh->tetrahedra.size) );
-
-  newShared->toSync = (HXT2Sync) {.mesh = mesh,
-                                  .allocMore = 0,
-                                  .otherArrays = {(void*) &newShared->quality.values,
-                                                  (void*) &newShared->date.values, NULL, NULL},
-                                  .otherArraysElementSize = {sizeof(double), sizeof(HXTTetDate), 0, 0},
-                                  .otherArraysSetDeleted = {qualitySetDeleted, NULL, NULL, NULL},
-                                  .threadFinished = 0};
-
-  #pragma omp parallel for
-  for (uint64_t i=0; i<mesh->tetrahedra.num; i++) {
-    newShared->date.values[i] = (HXTTetDate) {0};
-
-    if(getProcessedFlag(mesh, i))
-      newShared->quality.values[i] = DBL_MAX; // exterior tetrahedra have maximum quality
-    else {
-      uint32_t* nodes = mesh->tetrahedra.node + 4*i;
-// #ifndef NDEBUG
-      if(nodes[3]==HXT_GHOST_VERTEX){
-        exit( HXT_ERROR_MSG(HXT_STATUS_ERROR, "ghost tetrahedra should have been set to processed") );
-      }
-// #endif
-      newShared->quality.values[i] = tetQuality(mesh, &newShared->quality, nodes[0], nodes[1], nodes[2], nodes[3]);
-    }
-  }
-
-  *shared = newShared;
-  return HXT_STATUS_OK;
-}
-
-static HXTStatus threadShared_destroy(ThreadShared** shared) {
-  HXT_CHECK( hxtAlignedFree(&(*shared)->quality.values) );
-  HXT_CHECK( hxtAlignedFree(&(*shared)->date.values) );
-  HXT_CHECK( hxtAlignedFree(&(*shared)->badTets.array));
-  HXT_CHECK( hxtFree(shared) );
-  return HXT_STATUS_OK;
-}
-
-
-
-/**************************************************************************
-  create/update/delete local structure, containing partitions definition
- **************************************************************************/
-
-static HXTStatus threadLocals_create(ThreadLocal** locals_ptr, HXTOptimizeOptions* options) {
-  int nthreads = options->numThreads;
-  ThreadLocal* newLocal;
-  HXT_CHECK( hxtMalloc(&newLocal, nthreads*sizeof(ThreadLocal)));
-
-  for (int threadID=0; threadID<nthreads; threadID++) {
-    HXT_CHECK( hxtAlignedMalloc(&newLocal[threadID].deleted.array, sizeof(uint64_t)*DELETED_BUFFER_SIZE) );
-    newLocal[threadID].deleted.size = DELETED_BUFFER_SIZE;
-    newLocal[threadID].deleted.num = 0;
-  }
-
-  *locals_ptr = newLocal;
-  return HXT_STATUS_OK;
-}
-
-
-static inline HXTStatus EdgeRemovalStructs_create(ThreadLocal* locals, ThreadShared* shared, int nThreads) {
-  for (int threadID=0; threadID<nThreads; threadID++) {
-    HXT_CHECK( hxtMalloc(&locals[threadID].edgeRemoval, sizeof(HXTEdgeRemovalData)) );
-    locals[threadID].edgeRemoval->deleted = &locals[threadID].deleted;
-    locals[threadID].edgeRemoval->partition = &locals[threadID].partition;
-    locals[threadID].edgeRemoval->quality = &shared->quality;
-    locals[threadID].edgeRemoval->date = &shared->date;
-    locals[threadID].edgeRemoval->toSync = &shared->toSync;
-  }
-  return HXT_STATUS_OK;
-}
-
-
-static inline HXTStatus EdgeRemovalStructs_destroy(ThreadLocal* locals, int nThreads) {
-  for (int threadID=0; threadID<nThreads; threadID++) {
-    HXT_CHECK( hxtFree(&locals[threadID].edgeRemoval) );
-  }
-  return HXT_STATUS_OK;
-}
-
-
-static inline HXTStatus SmoothingStructs_create(ThreadLocal* locals, ThreadShared* shared,
-                                                int nThreads, uint32_t numVerticesConstrained) {
-  for (int threadID=0; threadID<nThreads; threadID++) {
-    HXT_CHECK( hxtMalloc(&locals[threadID].smoothing, sizeof(HXTSmoothingData)) );
-    locals[threadID].smoothing->mesh = shared->toSync.mesh;
-    locals[threadID].smoothing->deleted = &locals[threadID].deleted;
-    locals[threadID].smoothing->partition = &locals[threadID].partition;
-    locals[threadID].smoothing->quality = &shared->quality;
-    locals[threadID].smoothing->date = &shared->date;
-    locals[threadID].smoothing->numVerticesConstrained = numVerticesConstrained;
-  }
-  return HXT_STATUS_OK;
-}
-
-
-static inline HXTStatus SmoothingStructs_destroy(ThreadLocal* locals, int nThreads) {
-  for (int threadID=0; threadID<nThreads; threadID++) {
-    HXT_CHECK( hxtFree(&locals[threadID].smoothing) );
-  }
-  return HXT_STATUS_OK;
-}
-
-// TODO: use a HHXTTetQualities in SPR...
-static inline HXTStatus SPRStructs_create(ThreadLocal* locals, ThreadShared* shared,
-                                          int nThreads) {
-  for (int threadID=0; threadID<nThreads; threadID++) {
-    HXT_CHECK( hxtMalloc(&locals[threadID].SPR, sizeof(HXTSPRData)) );
-    locals[threadID].SPR->quality = &shared->quality;
-    locals[threadID].SPR->date = &shared->date;
-    locals[threadID].SPR->dateOfLastCheck = 0;
-    locals[threadID].SPR->dateOfLastCreation = 0;
-    locals[threadID].SPR->maxSearchNodes = 500;
-    locals[threadID].SPR->deleted = &locals[threadID].deleted;
-    locals[threadID].SPR->toSync = &shared->toSync;
-    locals[threadID].SPR->partition = &locals[threadID].partition;
-  }
-  return HXT_STATUS_OK;
-}
-
-
-static inline HXTStatus SPRStructs_destroy(ThreadLocal* locals, HXTOptimizeOptions* options) {
-  int nthreads = options->numThreads;
-  for (int threadID=0; threadID<nthreads; threadID++) {
-    HXT_CHECK( hxtFree(&locals[threadID].SPR) );
-  }
-  return HXT_STATUS_OK;
-}
-
-static Statistic threadLocals_collectStats(ThreadLocal* locals, int nThreads) {
-      // check the stat to see if we keep the same number of threads and if we move partitions
-  Statistic stat = {0,0,0,0};
-
-  for (int threadID=0; threadID<nThreads; threadID++)
-  {
-    stat.attempt += locals[threadID].stat.attempt;
-    stat.conflict += locals[threadID].stat.conflict;
-    stat.success += locals[threadID].stat.success;
-    stat.failure += locals[threadID].stat.failure;
-  }
-  return stat;
-}
-
-// this
-static HXTStatus threadLocals_update(HXTMesh* mesh, HXTBbox* bbox,
-                                     ThreadShared* shared, ThreadLocal* locals,
-                                     uint32_t* seed, int changePartitions) {
-
-  // initialize statistics
-  for (int threadID=0; threadID<shared->numThreads; threadID++) {
-    locals[threadID].stat = (Statistic) {0};
-  }
-
-  if(shared->numThreads>1) {
-    HXTVertex* vertices = (HXTVertex*) mesh->vertices.coord;
-    HXTGroup2* badTets = shared->badTets.array;
-
-    double indexShift = (double) hxtReproducibleLCG(seed)/RAND_MAX;
-
-    if(changePartitions) {
-      double hxtDeclareAligned bboxShift[3];
-
-      bboxShift[0] = (double) hxtReproducibleLCG(seed)/RAND_MAX;
-      bboxShift[1] = (double) hxtReproducibleLCG(seed)/RAND_MAX;
-      bboxShift[2] = (double) hxtReproducibleLCG(seed)/RAND_MAX;
-
-      HXT_CHECK( hxtMoore(bbox, vertices, mesh->vertices.num, bboxShift) );
-    }
-
-    #pragma omp parallel for simd aligned(badTets:SIMD_ALIGN)
-    for (uint64_t i=0; i<shared->badTets.num; i++) {
-      uint32_t firstNode = mesh->tetrahedra.node[4*badTets[i].v[1]];
-      badTets[i].v[0] = vertices[firstNode].padding.hilbertDist;
-    }
-
-    // sort the bad tetrahedrons following their first node hilbert dist
-    HXT_CHECK(  group2_sort_v0(badTets, shared->badTets.num, (UINT64_C(1)<<63) - 1) );
-
-    if(badTets[0].v[0]==badTets[shared->badTets.num-1].v[0]) {
-      // only one partition possible, everything is in the same cell !
-      shared->numThreads = 1;
-      locals[0].partition.startDist = 0;
-      locals[0].partition.lengthDist = UINT64_MAX;
-      locals[0].partition.firstElem = 0;
-      locals[0].partition.numElem = shared->badTets.num;
-      return HXT_STATUS_OK;
-    }
-
-    const double step = shared->badTets.num/shared->numThreads;
-
-    #pragma omp parallel num_threads(shared->numThreads)
-    {
-      const int threadID = omp_get_thread_num();
-
-      uint64_t first = MIN((uint64_t) step*(threadID+1)-1, (uint64_t) (step*(threadID + indexShift)));
-      uint64_t startDist = badTets[first].v[0];
-
-      uint64_t up = 1;
-      while(first+up<shared->badTets.num && startDist==badTets[first + up].v[0])
-        up++;
-
-      first = first+up==shared->badTets.num?0:first+up;
-      if(first > 0)
-        startDist = (badTets[first].v[0] + badTets[first - 1].v[0] + 1)/2;
-      else
-        startDist = badTets[shared->badTets.num-1].v[0] + 
-                   (badTets[first].v[0] - badTets[shared->badTets.num - 1].v[0])/2;
-
-      locals[threadID].partition.firstElem = first;
-      locals[threadID].partition.startDist = startDist;
-
-      #pragma omp barrier
-
-      uint64_t firstNext = locals[(threadID+1)%shared->numThreads].partition.firstElem;
-      uint64_t endDist = locals[(threadID+1)%shared->numThreads].partition.startDist;
-      locals[threadID].partition.numElem = (firstNext + shared->badTets.num - first)%shared->badTets.num;
-      locals[threadID].partition.lengthDist = endDist - startDist;
-
-      uint64_t rel = endDist - startDist;
-
-      // dismiss tetrahedron that are in our list but not in our partition
-      for (uint64_t i=0; i<locals[threadID].partition.numElem; i++) {
-        uint64_t index = (locals[threadID].partition.firstElem + i)%shared->badTets.num;
-        uint64_t curTet = shared->badTets.array[index].v[1];
-
-        uint32_t* nodes = mesh->tetrahedra.node + 4*curTet;
-
-        if(vertexOutOfPartition(vertices, nodes[0], rel, startDist) + 
-           vertexOutOfPartition(vertices, nodes[1], rel, startDist) + 
-           vertexOutOfPartition(vertices, nodes[2], rel, startDist) + 
-           vertexOutOfPartition(vertices, nodes[3], rel, startDist) > 1) {
-          shared->badTets.array[index].v[1] = HXT_NO_ADJACENT;
-          locals[threadID].stat.attempt++;
-          locals[threadID].stat.conflict++;
-        }
-      }
-    }
-  }
-  else {
-    // TODO: when there is only one thread, we could sort bad tetrahedra from worst to best...
-    locals[0].partition.startDist = 0;
-    locals[0].partition.lengthDist = UINT64_MAX;
-    locals[0].partition.firstElem = 0;
-    locals[0].partition.numElem = shared->badTets.num;
-  }
-
-  return HXT_STATUS_OK;
-}
-
-
-static HXTStatus threadLocals_destroy(ThreadLocal** local, int nthreads) {
-  for (int threadID=0; threadID<nthreads; threadID++) {
-    HXT_CHECK( hxtAlignedFree(&(*local)[threadID].deleted.array) );
-  }
-
-  HXT_CHECK( hxtFree(local) );
-  return HXT_STATUS_OK;
-}
-
-
-/* once the SPR is done, the current date should be changed to the date of the lastCheck */
-static void SPRDates_update(ThreadShared* shared, ThreadLocal* locals)
-{
-  uint16_t lastCheck = 0;
-  for(int threadID=0; threadID<shared->numThreads; threadID++) {
-    if(locals[threadID].SPR->dateOfLastCheck > lastCheck)
-      lastCheck = locals[threadID].SPR->dateOfLastCheck;
-  }
-
-  shared->date.current = lastCheck;
-
-  for(int threadID=0; threadID<shared->numThreads; threadID++) {
-    locals[threadID].SPR->dateOfLastCheck = lastCheck;
-    locals[threadID].SPR->dateOfLastCreation = lastCheck;
-  }
-}
-
-
-static double meanQuality(HXTMesh* mesh, double* quality) {
-  double mean = 0;
-  uint64_t ntet = 0;
-  #pragma omp parallel for reduction(+:mean,ntet)
-  for (uint64_t i=0; i<mesh->tetrahedra.num; i++) {
-    if(quality[i]!=DBL_MAX){
-      ntet++;
-      mean += quality[i];
-    }
-  }
-  mean/=ntet;
-  return mean;
-}
-
-
-static double minQuality(HXTMesh* mesh, double* quality) {
-  double min = DBL_MAX;
-
-  #pragma omp parallel for reduction(min:min)
-  for (uint64_t i=0; i<mesh->tetrahedra.num; i++) {
-    if(quality[i]!=DBL_MAX)
-      min = fmin(quality[i], min);
-  }
-
-  return min;
-}
-
-
-static uint64_t badTetrahedra(HXTMesh* mesh, double* quality, double threshold) {
-  uint64_t count = 0;
-
-  #pragma omp parallel for reduction(+:count)
-  for (uint64_t i=0; i<mesh->tetrahedra.num; i++)
-  {
-    if(quality[i]<threshold)
-      count++;
-  }
-  return count;
-}
-
-
-// TODO: some thing are seriously wrongly done
-static inline void stage0_heuristic(Statistic stage0, Statistic stage1, uint64_t numBad,
-                             int* numThreads, int* changePartitions) {
-  if(numBad < (uint64_t) *numThreads*16) {
-    *numThreads = MAX(1, numBad/16);
-    // *changePartitions = 1;
-  }
-
-  if(stage0.attempt==0) // first time, we just return
-    return;
-
-  // too much conflict
-  if(stage0.conflict>=stage0.attempt){
-    // puts("too much conflict");
-    *numThreads = 1;
-    return;
-  }
-
-  // not enough success
-  if(stage0.conflict > 10*stage0.success) {
-    // int n = stage0.conflict / (10*stage0.success+1);
-    // puts("not enough success");
-    *numThreads = (*numThreads+1)/2;
-    // *changePartitions = 1;
-  }
-
-  if(*numThreads>1)
-    *changePartitions = 1;
-
-  HXT_UNUSED(stage1);
-}
-
-
-static inline int continue_stage0(Statistic stage0, Statistic stage1) {
-  HXT_UNUSED(stage1);
-
-  return stage0.success>16 || stage0.conflict;
-}
-
-
-static inline void stage1_heuristic(Statistic stage0, Statistic stage1, uint64_t numBad,
-                             int* numThreads) {
-  if(numBad < (uint64_t) *numThreads*2) {
-    *numThreads = MAX(1, numBad/2);
-  }
-
-  if(stage1.attempt==0) // first time, we just return
-    return;
-
-  if(stage1.attempt > 32*stage1.success) {
-    *numThreads = (*numThreads+1)/2;
-  }
-
-  HXT_UNUSED(stage0);
-}
-
-
-static inline int continue_stage1(Statistic stage1) {
-  return stage1.success || stage1.conflict;
-}
-
-
-/**************************************************************************
-***************************************************************************
-
-                    main function, optimizes a mesh
-
- **************************************************************************
- **************************************************************************/
-
-HXTStatus hxtOptimizeTetrahedra(HXTMesh *mesh,
-                                HXTOptimizeOptions* options){
-  ThreadLocal* locals = NULL;
-  ThreadShared* shared = NULL;
-  volatile HXTStatus globalStatus = HXT_STATUS_OK;
-  uint32_t seed = 1;
-  
-  if(options->numThreads<0)
-    options->numThreads = omp_get_num_procs();
-  else if(options->numThreads==0)
-    options->numThreads = omp_get_max_threads();
-
-  HXTBbox bbox;
-  if(options->bbox==NULL) {
-    hxtBboxAdd(&bbox, mesh->vertices.coord, mesh->vertices.num);
-  }
-  else {
-    bbox = *options->bbox;
-  }
-
-  HXT_CHECK( threadShared_create(mesh, options, &shared) );
-  HXT_CHECK( threadLocals_create(&locals, options) );
-  HXT_CHECK( EdgeRemovalStructs_create(locals, shared, options->numThreads));
-  HXT_CHECK( SmoothingStructs_create(locals, shared, options->numThreads, options->numVerticesConstrained));
-  HXT_CHECK( SPRStructs_create(locals, shared, options->numThreads) );
-
-  int iter = 0;
-  int SPRnumThreads = options->numThreads;
-  Statistic stage0;
-  Statistic stage1 = {0};
-
-  do {
-    HXT_INFO_COND(options->verbosity>0,
-                  "Optimization stage %u.0: smoothing and edge removal", iter);
-
-    int changePartitions = 1;
-    shared->numThreads = options->numThreads;
-    stage0 = (Statistic) {0};
-
-    do {
-      // double time00 = omp_get_wtime();
-      // create a list of bad tets
-      HXT_CHECK( threadShared_update(mesh, shared) );
-      if(shared->badTets.num==0)
-        break;
-
-      stage0_heuristic(stage0, stage1, shared->badTets.num, &shared->numThreads, &changePartitions);
-
-      // create partitions
-      HXT_CHECK( threadLocals_update(mesh, &bbox, shared, locals, &seed, changePartitions) );
-
-      HXT_INFO_COND(options->verbosity>0, "   "
-                    HXTu64 " bad tetrahedra being optimized on %d threads",
-                    shared->badTets.num, shared->numThreads);
-
-      #pragma omp parallel num_threads(shared->numThreads)
-      {
-        const int threadID = omp_get_thread_num();
-        ThreadLocal* local = locals + threadID;
-
-        for (uint64_t i=0; i<local->partition.numElem && globalStatus==HXT_STATUS_OK; i++) {
-          uint64_t index = (local->partition.firstElem + i)%shared->badTets.num;
-          uint64_t curTet = shared->badTets.array[index].v[1];
-
-          if(curTet==HXT_NO_ADJACENT || shared->quality.values[curTet]>= shared->quality.threshold)
-            continue;
-
-          HXTStatus status=HXT_STATUS_OK;
-          for (int edge=0; edge<6; edge++) {
-            unsigned facet0, facet1;
-            getFacetsFromEdge(edge, &facet0, &facet1);
-
-            local->stat.attempt++;
-            status = hxtEdgeRemoval_opti(local->edgeRemoval, curTet, edge);
-            if(status==HXT_STATUS_CONFLICT)
-              local->stat.conflict++;
-            else if(status==HXT_STATUS_OK){
-              local->stat.success++;
-              break;
-            }
-            else if(status>HXT_STATUS_INTERNAL) {
-              // fatal error
-              break;
-            }
-          }
-
-          /*** make a swap whenever it is possible and it is an improvement ***/
-          if(status<=HXT_STATUS_INTERNAL) {
-            for (int vertex=0; vertex<4; vertex++) {
-              local->stat.attempt++;
-              status = hxtSmoothing(local->smoothing, 4*curTet+vertex);
-              if(status==HXT_STATUS_CONFLICT)
-                local->stat.conflict++;
-              else if(status==HXT_STATUS_OK) {
-                local->stat.success++;
-                break;
-              }
-              else if(status>HXT_STATUS_INTERNAL) {
-                // fatal error
-                break;
-              }
-            }
-          }
-
-          if(status<=HXT_STATUS_INTERNAL) { // the cavity could not be modified
-            local->stat.failure++;
-            continue;
-          }
-          else if(status!=HXT_STATUS_OK) {
-            #pragma omp atomic write
-            globalStatus = status;
-            break;
-          }
-        }
-
-        HXTStatus status = waitForPossibleReallocation(&shared->toSync, shared->numThreads);
-        if(status!=HXT_STATUS_OK) {
-          #pragma omp atomic write
-            globalStatus = status;
-        }
-      }
-
-      if(globalStatus!=HXT_STATUS_OK){
-        HXT_TRACE(globalStatus);
-        return globalStatus;
-      }
-
-      stage0 = threadLocals_collectStats(locals, shared->numThreads);
-      HXT_INFO_COND(options->verbosity>1, "   "
-                    HXTu64 " attempts, " HXTu64 " modifications, " HXTu64 " conflict, " HXTu64 " failures",
-                    stage0.attempt,      stage0.success,           stage0.conflict,     stage0.failure);
-      // double time01 = omp_get_wtime();
-      // printf("Smoothing & ER took %f s/tet,  %f modif/tet, %f conflict/attempt\n",
-      //        (time01 - time00)/(stage0.success + stage0.failure),
-      //        (double) stage0.success/(stage0.success + stage0.failure),
-      //        (double) stage0.conflict/stage0.attempt);
-    } while(continue_stage0(stage0, stage1));
-
-    // if we exited previous loop, we need to exit this one again
-    if(shared->badTets.num==0)
-      break;
-
-    // Now, one pass of SPR
-    HXT_INFO_COND(options->verbosity>0,
-                  "Optimization stage %u.1: small polyhedron reconnection", iter);
-
-    // double time1 = omp_get_wtime();
-
-    // create a list of bad tets
-    HXT_CHECK( threadShared_update(mesh, shared) );
-    if(shared->badTets.num==0)
-      break;
-
-    stage1_heuristic(stage0, stage1, shared->badTets.num, &SPRnumThreads);
-    shared->numThreads = SPRnumThreads;
-    changePartitions = 1;
-
-    // create partitions
-    HXT_CHECK( threadLocals_update(mesh, &bbox, shared, locals, &seed, changePartitions) );
-
-    HXT_INFO_COND(options->verbosity>0, "   "
-                  HXTu64 " bad tetrahedra being optimized on %d threads",
-                  shared->badTets.num, shared->numThreads);
-
-    #pragma omp parallel num_threads(shared->numThreads)
-    {
-      const int threadID = omp_get_thread_num();
-      ThreadLocal* local = locals + threadID;
-
-      for (uint64_t i=0; i<local->partition.numElem && globalStatus==HXT_STATUS_OK; i++) {
-        uint64_t index = (local->partition.firstElem + i)%shared->badTets.num;
-        uint64_t curTet = shared->badTets.array[index].v[1];
-
-        if(curTet==HXT_NO_ADJACENT || shared->quality.values[curTet]>= shared->quality.threshold)
-          continue;
-
-        local->stat.attempt++;
-
-        HXTStatus status = hxtSPR_opti(local->SPR, curTet);
-
-        if(status==HXT_STATUS_CONFLICT){
-          local->stat.conflict++;
-          local->stat.failure++;
-        }
-        else if(status==HXT_STATUS_OK)
-          local->stat.success++;
-        else if(status==HXT_STATUS_INTERNAL)
-          local->stat.failure++;
-        else {
-          // fatal error
-          #pragma omp atomic write
-          globalStatus = status;
-          break;
-        }
-
-      //   // complete verification
-      //   for (int threadID=0; threadID<options->numThreads; threadID++) {
-      //     for (uint64_t i=0; i<locals[threadID].deleted.num; i++) {
-      //       uint64_t delTet = locals[threadID].deleted.array[i];
-      // #ifdef DEBUG
-      //       if(!getDeletedFlag(mesh, delTet))
-      //         return HXT_ERROR_MSG(HXT_STATUS_ERROR, "deleted flag not set on deleted tet");
-      //       if(shared->quality.values[delTet]!=DBL_MAX)
-      //         return HXT_ERROR_MSG(HXT_STATUS_ERROR, "quality of deleted tet %lu should have been set to DBL_MAX", delTet);
-      // #endif
-      //       for (int j=0; j<4; j++)
-      //         mesh->tetrahedra.neigh[4*delTet+j] = HXT_NO_ADJACENT;
-      //     }
-      //   }
-
-      //   HXT_CHECK( hxtRemoveDeleted(mesh) );
-      //   local->deleted.num = 0;
-      }
-      
-      HXTStatus status = waitForPossibleReallocation(&shared->toSync, shared->numThreads);
-      if(status!=HXT_STATUS_OK) {
-        #pragma omp atomic write
-          globalStatus = status;
-      }
-    }
-
-    if(globalStatus!=HXT_STATUS_OK){
-      HXT_TRACE(globalStatus);
-      return globalStatus;
-    }
-
-    SPRDates_update(shared, locals);
-
-    stage1 = threadLocals_collectStats(locals, shared->numThreads);
-    HXT_INFO_COND(options->verbosity>1, "   "
-                  HXTu64 " attempts, " HXTu64 " modifications, " HXTu64 " conflict",
-                  stage1.attempt,       stage1.success,           stage1.conflict);
-    // double time2 = omp_get_wtime();
-    // printf("SPR took %f s/tet,  %f modif/tet, %f conflict/attempt\n",
-    //          (time2 - time1)/(stage1.success + stage1.failure),
-    //          (double) stage1.success/(stage1.success + stage1.failure),
-    //          (double) stage1.conflict/stage1.attempt);
-
-    iter++;
-  } while(continue_stage1(stage1));
-
-  HXT_CHECK( SPRStructs_destroy(locals, options) );
-  HXT_CHECK( EdgeRemovalStructs_destroy(locals, options->numThreads) );
-  HXT_CHECK( SmoothingStructs_destroy(locals, options->numThreads) );
-
-  HXT_INFO_COND(options->verbosity>0, "   "
-                "\n\t" HXTu64" bad tet. | mean quality: %f | min quality: %f\n",
-                badTetrahedra(mesh, shared->quality.values, shared->quality.threshold),
-                meanQuality(mesh, shared->quality.values),
-                minQuality(mesh, shared->quality.values));
-
-  for (int threadID=0; threadID<options->numThreads; threadID++) {
-    for (uint64_t i=0; i<locals[threadID].deleted.num; i++) {
-      uint64_t delTet = locals[threadID].deleted.array[i];
-#ifdef DEBUG
-      if(!getDeletedFlag(mesh, delTet))
-        return HXT_ERROR_MSG(HXT_STATUS_ERROR, "deleted flag not set on deleted tet");
-      if(shared->quality.values[delTet]!=DBL_MAX)
-        return HXT_ERROR_MSG(HXT_STATUS_ERROR, "quality of deleted tet should have been set to DBL_MAX");
-#endif
-      for (int j=0; j<4; j++)
-        mesh->tetrahedra.neigh[4*delTet+j] = HXT_NO_ADJACENT;
-    }
-  }
-
-#ifdef DEBUG
-  HXT_CHECK( hxtTetVerify(mesh) );
-#endif
-
-  HXT_CHECK( hxtRemoveDeleted(mesh) );
-
-  HXT_CHECK( threadLocals_destroy(&locals, options->numThreads) );
-  HXT_CHECK( threadShared_destroy(&shared) );
-
-  return HXT_STATUS_OK;
-}
-
diff --git a/contrib/hxt/hxt_tetOptiDate.h b/contrib/hxt/hxt_tetOptiDate.h
deleted file mode 100644
index 22b993f46b..0000000000
--- a/contrib/hxt/hxt_tetOptiDate.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef _HXT_TETOPTIDATE_
-#define _HXT_TETOPTIDATE_
-
-#include "stdint.h"
-
-typedef struct {
-  uint16_t creation;
-  uint16_t check;
-} HXTTetDate;
-
-typedef struct {
-  HXTTetDate* values;
-  uint16_t current;
-} HXTTetDates;
-
-
-
-
-#endif
\ No newline at end of file
diff --git a/contrib/hxt/hxt_tetPartition.h b/contrib/hxt/hxt_tetPartition.h
deleted file mode 100644
index 0b011c9a9c..0000000000
--- a/contrib/hxt/hxt_tetPartition.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef _HXT_TETPARTITION_
-#define _HXT_TETPARTITION_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#include "hxt_vertices.h"
-
-typedef struct {
-    uint64_t startDist;
-    uint64_t lengthDist;
-    uint64_t firstElem;
-    uint64_t numElem;
-} HXTPartition;
-
-
-/* simple utility function to tell if a vertex is inside a partition,
- * given the partition start and it's length 'rel'
- * !!! Does not work with ghost vertex !!! */
-static inline int vertexOutOfPartition(HXTVertex* vertices, uint32_t v, uint64_t lengthDist, uint64_t startDist) {
-  // unsigned wrap around is defined by the standard
-  return vertices[v].padding.hilbertDist - startDist >= lengthDist;
-}
-
-
-// HXTStatus hxtComputePartitions(HXTPartition* partitions[], int nThreads, uint64_t* hilbertDist, uint64_t n);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/contrib/hxt/hxt_tetPostpro.c b/contrib/hxt/hxt_tetPostpro.c
deleted file mode 100644
index 3aa691fb46..0000000000
--- a/contrib/hxt/hxt_tetPostpro.c
+++ /dev/null
@@ -1,182 +0,0 @@
-#include "predicates.h"
-#include "hxt_tetPostpro.h"
-#include "hxt_tetFlag.h"
-#include "hxt_tetUtils.h"
-#include "hxt_vertices.h"
-
-
-static void verticesPlaneOrient(HXTMesh* mesh, double* __restrict__ p0, double* __restrict__ p1, double* __restrict__ p2){
-  #pragma omp parallel for
-  for (uint32_t i=0; i<mesh->vertices.num; i++) {
-    mesh->vertices.coord[4*i+3] = orient3d(p0, p1, p2, mesh->vertices.coord + 4*i);
-  }
-}
-
-/** keep only tetrahedra whose intersection with a plane is not empty.
-The plane is defined by 3 points. */
-HXTStatus hxtTetPlaneIntersection(HXTMesh* mesh, double* p0, double* p1, double* p2){
-  verticesPlaneOrient(mesh, p0, p1, p2);
-
-  #pragma omp parallel for
-  for (uint64_t i=0; i<mesh->tetrahedra.num; i++) {
-    if(mesh->tetrahedra.node[4*i+3] == HXT_GHOST_VERTEX) {
-      setDeletedFlag(mesh, i);
-    }
-    else {
-      double firstOrient = mesh->vertices.coord[4*mesh->tetrahedra.node[4*i]+3];
-      for (int j=1; j<4; j++) {
-        double secondOrient = mesh->vertices.coord[4*mesh->tetrahedra.node[4*i+j]+3];
-        if(firstOrient*secondOrient<=0.0){
-          firstOrient = 0.0;
-          break;
-        }
-      }
-
-      if(firstOrient!=0.0)
-        setDeletedFlag(mesh, i);
-    }
-  }
-
-  HXT_CHECK( hxtRemoveDeleted(mesh) );
-
-  return HXT_STATUS_OK;
-}
-
-/** keep only tetrahedra with at least two vertices on the positive side of the plane {p0,p1,p2}.
-(p is on the positive side <=> orient3d(p0,p1,p2, p) > 0)
-When seen from the negative side, p0,p1,p2 is counter-clockwise  */
-HXTStatus hxtTetPlaneOrient(HXTMesh* mesh, double* p0, double* p1, double* p2){
-  verticesPlaneOrient(mesh, p0, p1, p2);
-
-  #pragma omp parallel for
-  for (uint64_t i=0; i<mesh->tetrahedra.num; i++) {
-    if(mesh->tetrahedra.node[4*i+3] == HXT_GHOST_VERTEX) {
-      setDeletedFlag(mesh, i);
-    }
-    else {
-      for (int j=0; j<4; j++) {
-        if(mesh->vertices.coord[4*mesh->tetrahedra.node[4*i+j]+3]<0.0){
-          setDeletedFlag(mesh, i);
-          break;
-        }
-      }
-    }
-  }
-
-  HXT_CHECK( hxtRemoveDeleted(mesh) );
-
-  return HXT_STATUS_OK;
-}
-
-
-/** keep only vertices that are either in the surface mesh or in the tetrahedra mesh */
-HXTStatus hxtFilterVertices(HXTMesh* mesh, double* nodalSizes){
-  HXTVertex* vertices = (HXTVertex*) mesh->vertices.coord;
-
-  #pragma omp parallel for
-  for (uint32_t i=0; i<mesh->vertices.num; i++) {
-    vertices[i].padding.status = HXT_STATUS_FALSE;
-  }
-
-  if(mesh->tetrahedra.node!=NULL){
-    #pragma omp parallel for
-    for (uint64_t i=0; i<mesh->tetrahedra.num; i++) {
-      vertices[mesh->tetrahedra.node[4*i+0]].padding.status = HXT_STATUS_TRUE;
-      vertices[mesh->tetrahedra.node[4*i+1]].padding.status = HXT_STATUS_TRUE;
-      vertices[mesh->tetrahedra.node[4*i+2]].padding.status = HXT_STATUS_TRUE;
-      vertices[mesh->tetrahedra.node[4*i+3]].padding.status = HXT_STATUS_TRUE;
-    }
-  }
-
-  if(mesh->triangles.node!=NULL){
-    #pragma omp parallel for
-    for (uint64_t i=0; i<mesh->triangles.num; i++) {
-      vertices[mesh->triangles.node[3*i+0]].padding.status = HXT_STATUS_TRUE;
-      vertices[mesh->triangles.node[3*i+1]].padding.status = HXT_STATUS_TRUE;
-      vertices[mesh->triangles.node[3*i+2]].padding.status = HXT_STATUS_TRUE;
-    }
-  }
-
-  if(mesh->lines.node!=NULL){
-    #pragma omp parallel for
-    for (uint64_t i=0; i<mesh->lines.num; i++) {
-      vertices[mesh->lines.node[2*i+0]].padding.status = HXT_STATUS_TRUE;
-      vertices[mesh->lines.node[2*i+1]].padding.status = HXT_STATUS_TRUE;
-    }
-  }
-
-  /* remove deleted vertices and change tetrahedra.node triangles.node and lines.nodes accordingly */
-  uint32_t* numInserted;
-  HXT_CHECK( hxtAlignedMalloc(&numInserted, omp_get_max_threads()*sizeof(uint32_t)) );
-  const uint32_t n = mesh->vertices.num;
-
-  // when a vertex was skipped, nodeInfo[i].status = HXT_STATUS_FALSE
-  #pragma omp parallel
-  {
-    uint32_t start = 0;
-    int threadID = omp_get_thread_num();
-    numInserted[threadID] = 0;
-
-    #pragma omp for schedule(static)
-    for (uint32_t i=0; i<n; i++) {
-      if(vertices[i].padding.status==HXT_STATUS_TRUE)
-        numInserted[threadID]++;
-    }// implicit barrier here
-
-    for (int i=0; i<threadID; i++) {
-      start+=numInserted[i];
-    }
-
-    // 3rd: compute where each vertices will be
-    #pragma omp for schedule(static)
-    for (uint32_t i=0; i<n; i++) {
-      uint32_t oldStart = start;
-
-      if(vertices[i].padding.status==HXT_STATUS_TRUE)
-        start++;
-
-      // index and status are at the same location (it's a union) we cannot put this above the "if" !
-      vertices[i].padding.index = oldStart;
-    }
-
-    // 4th: update tetrahedra.node accordingly
-    if(mesh->tetrahedra.node!=NULL){
-      #pragma omp for
-      for (uint64_t i=0; i<4*mesh->tetrahedra.num; i++) {
-        uint32_t index = mesh->tetrahedra.node[i];
-        if(index!=HXT_GHOST_VERTEX)
-          mesh->tetrahedra.node[i] = vertices[index].padding.index;
-      }
-    }
-
-    if(mesh->triangles.node!=NULL){
-      #pragma omp for
-      for (uint64_t i=0; i<3*mesh->triangles.num; i++) {
-        uint32_t index = mesh->triangles.node[i];
-        mesh->triangles.node[i] = vertices[index].padding.index;
-      }
-    }
-
-    if(mesh->lines.node!=NULL){
-      #pragma omp for
-      for (uint64_t i=0; i<2*mesh->lines.num; i++) {
-        uint32_t index = mesh->lines.node[i];
-        mesh->lines.node[i] = vertices[index].padding.index;
-      }
-    }
-  }
-
-  HXT_CHECK( hxtAlignedFree(&numInserted) );
-
-  // 5th: put vertices at the right indices
-  for (uint32_t i=0; i<mesh->vertices.num; i++) {
-    if(nodalSizes!=NULL){
-      nodalSizes[vertices[i].padding.index] = nodalSizes[i];
-    }
-    vertices[vertices[i].padding.index] = vertices[i];
-  }
-
-  mesh->vertices.num = vertices[mesh->vertices.num-1].padding.index + 1;
-
-  return HXT_STATUS_OK;
-}
diff --git a/contrib/hxt/hxt_tetPostpro.h b/contrib/hxt/hxt_tetPostpro.h
deleted file mode 100644
index 62ebd5cc35..0000000000
--- a/contrib/hxt/hxt_tetPostpro.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef _HXT_TETPOSTPRO_
-#define _HXT_TETPOSTPRO_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "hxt_mesh.h"
-
-/**
-* \file hxt_tetPospro.h postprocessing to keep only some part of a tetrahedra mesh
-* \author Célestin Marot
-*/
-
-/** keep only tetrahedra whose intersection with a plane is not empty.
-The plane is defined by 3 points. */
-HXTStatus hxtTetPlaneIntersection(HXTMesh* mesh, double* p0, double* p1, double* p2);
-
-/** keep only tetrahedra with at least two vertices on the positive side of the plane {p0,p1,p2}.
-(p is on the positive side <=> orient3d(p0,p1,p2, p) > 0)
-When seen from the negative side, p0,p1,p2 is counter-clockwise  */
-HXTStatus hxtTetPlaneOrient(HXTMesh* mesh, double* p0, double* p1, double* p2);
-
-/** keep only vertices that are either in the surface mesh or in the tetrahedra mesh */
-HXTStatus hxtFilterVertices(HXTMesh* mesh, double* nodalSizes);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/contrib/hxt/hxt_tetQuality.c b/contrib/hxt/hxt_tetQuality.c
deleted file mode 100644
index 6543af70d0..0000000000
--- a/contrib/hxt/hxt_tetQuality.c
+++ /dev/null
@@ -1,254 +0,0 @@
-#include <math.h>
-#include <float.h>
-#include "predicates.h"
-
-static inline void hxt_cross_prod(double a[3], double b[3], double c[3])
-{
-  c[0] = a[1] * b[2] - a[2] * b[1];
-  c[1] = a[2] * b[0] - a[0] * b[2];
-  c[2] = a[0] * b[1] - a[1] * b[0];
-}
-
-static inline double hxt_distance2(double p0[3], double p1[3]){
-  double a = p0[0]-p1[0];
-  double b = p0[1]-p1[1];
-  double c = p0[2]-p1[2];
-  return a*a+b*b+c*c;
-}
-
-double hxt_triangle_area(double p0[3], double p1[3], double p2[3])
-{
-  double a[3], b[3], c[3];
-
-  a[0] = p2[0] - p1[0];
-  a[1] = p2[1] - p1[1];
-  a[2] = p2[2] - p1[2];
-
-  b[0] = p0[0] - p1[0];
-  b[1] = p0[1] - p1[1];
-  b[2] = p0[2] - p1[2];
-
-  hxt_cross_prod(a, b, c);
-  return 0.5 * sqrt(c[0] * c[0] + c[1] * c[1] + c[2] * c[2]);
-}
-
-double hxtTetDeterminantInexact(double a[3],  double b[3], double c[3], double d[3], void* userData) {
-HXT_UNUSED(userData);
-  
-  double ab[3], ac[3], ad[3];
-  for (int i=0; i<3; i++) {
-    ab[i] = b[i] - a[i]; // AB
-    ac[i] = c[i] - a[i]; // AC
-    ad[i] = d[i] - a[i]; // AD
-  }
- 
-  double acxad0 = ac[1]*ad[2] - ac[2]*ad[1];
-  double adxab0 = ad[1]*ab[2] - ad[2]*ab[1];
-  double abxac0 = ab[1]*ac[2] - ab[2]*ac[1];
-  double volume6 = ab[0]*acxad0 + ac[0]*adxab0 + ad[0]*abxac0;
- 
-  return volume6;
-}
-
-
-double hxtTetAspectRatio (double p0[3],  double p1[3], double p2[3], double p3[3], void* userData) {
-  HXT_UNUSED(userData);
-
-  double volume = -orient3d (p0,p1,p2,p3) / 6.0;
-
-  double s1 = fabs(hxt_triangle_area(p0, p1, p2));
-  double s2 = fabs(hxt_triangle_area(p0, p2, p3));
-  double s3 = fabs(hxt_triangle_area(p0, p1, p3));
-  double s4 = fabs(hxt_triangle_area(p1, p2, p3));
-
-  double rhoin = 3. * volume / (s1 + s2 + s3 + s4);
-  double l  = hxt_distance2 (p0,p1);
-  double l2 = hxt_distance2 (p0,p2);
-  double l3 = hxt_distance2 (p0,p3);
-  double l4 = hxt_distance2 (p1,p2);
-  double l5 = hxt_distance2 (p1,p3);
-  double l6 = hxt_distance2 (p2,p3);
-
-  l = l2 > l ? l2:l;
-  l = l3 > l ? l3:l;
-  l = l4 > l ? l4:l;
-  l = l5 > l ? l5:l;
-  l = l6 > l ? l6:l;
-  
-  return sqrt(24./l) * rhoin ;
-}
-
-
-
-//!\ this function does not return the aspect ratio 'r'. It returns 'r^2/24'
-double hxtTetAspectFastRatio (double a[3],  double b[3], double c[3], double d[3], void* userData) {
-  HXT_UNUSED(userData);
-  
-  double ab[3], ac[3], ad[3], bc[3], cd[3], db[3];
-  for (int i=0; i<3; i++) {
-    ab[i] = b[i] - a[i]; // AB
-    ac[i] = c[i] - a[i]; // AC
-    ad[i] = d[i] - a[i]; // AD
-  }
- 
-  double acxad0 = ac[1]*ad[2] - ac[2]*ad[1];
-  double adxab0 = ad[1]*ab[2] - ad[2]*ab[1];
-  double abxac0 = ab[1]*ac[2] - ab[2]*ac[1];
-  double volume6 = ab[0]*acxad0 + ac[0]*adxab0 + ad[0]*abxac0;
- 
-   // abort as early as possible
-  if(volume6<=0.0)
-    return 0.0;
- 
-  double acxad1 = ac[2]*ad[0] - ac[0]*ad[2];
-  double acxad2 = ac[0]*ad[1] - ac[1]*ad[0];
- 
-  double adxab1 = ad[2]*ab[0] - ad[0]*ab[2];
-  double adxab2 = ad[0]*ab[1] - ad[1]*ab[0];
- 
-  double abxac1 = ab[2]*ac[0] - ab[0]*ac[2];
-  double abxac2 = ab[0]*ac[1] - ab[1]*ac[0];
-
-  for (int i=0; i<3; i++) {
-    db[i] = b[i] - d[i]; // DB = B-D = AB-AD
-    bc[i] = c[i] - b[i]; // BC = C-B = AC-AB
-    cd[i] = d[i] - c[i]; // CD = D-c = AD-AC
-  }
- 
-  double bcxcd0 = bc[1]*cd[2] - bc[2]*cd[1]; // = acxad0+abxac0+adxab0;
-  double bcxcd1 = bc[2]*cd[0] - bc[0]*cd[2]; // = acxad1+abxac1+adxab1;
-  double bcxcd2 = bc[0]*cd[1] - bc[1]*cd[0]; // = acxad2+abxac2+adxab2;
-
-  double areaSum = sqrt(acxad0*acxad0 + acxad1*acxad1 + acxad2*acxad2)
-                 + sqrt(adxab0*adxab0 + adxab1*adxab1 + adxab2*adxab2)
-                 + sqrt(abxac0*abxac0 + abxac1*abxac1 + abxac2*abxac2)
-                 + sqrt(bcxcd0*bcxcd0 + bcxcd1*bcxcd1 + bcxcd2*bcxcd2);
-
-  double l = ab[0]*ab[0] + ab[1]*ab[1] + ab[2]*ab[2]; // |AB|²
-  double l2 = ac[0]*ac[0] + ac[1]*ac[1] + ac[2]*ac[2]; // |AC|²
-  double l3 = ad[0]*ad[0] + ad[1]*ad[1] + ad[2]*ad[2]; // |AD|²
-  double l4 = bc[0]*bc[0] + bc[1]*bc[1] + bc[2]*bc[2]; // |BC|²
-  double l5 = cd[0]*cd[0] + cd[1]*cd[1] + cd[2]*cd[2]; // |CD|²
-  double l6 = db[0]*db[0] + db[1]*db[1] + db[2]*db[2]; // |DB|²
-
-  if(l2>l) l=l2;
-  if(l3>l) l=l3;
-  if(l4>l) l=l4;
-  if(l5>l) l=l5;
-  if(l6>l) l=l6;
-
-  return volume6*volume6/(l*areaSum*areaSum);
-}
-
-
-
-
-// static inline double vec_dot(double a[3], double b[3]) {
-//   return a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
-// }
-
-// static inline double vec_norm(double v[3]) {
-//   return vec_dot(v,v);
-// }
-
-// double myOwnAspectRatio(double a[3],  double b[3], double c[3], double d[3]) {
-//   double edges[6][4];
-//   for (int i=0; i<3; i++) {
-//     edges[0][i] = b[i] - a[i];
-//     edges[1][i] = c[i] - b[i];
-//     edges[2][i] = d[i] - c[i];
-//     edges[3][i] = a[i] - d[i];
-//     edges[4][i] = c[i] - a[i];
-//     edges[5][i] = d[i] - b[i];
-//   }
-
-//   double normal[4][4];
-//   const unsigned ci[4] = {1,2,0,1};
-
-//   for (unsigned j=0; j<3; j++) {
-//     for (unsigned i=0; i<4; i++) {
-//       normal[i][j] = edges[(i+1)&3][ci[j]]*edges[(i+2)&3][ci[j+1]] - edges[(i+2)&3][ci[j]]*edges[(i+1)&3][ci[j+1]];
-//     }
-//   }
-
-//    // abort as early as possible
-//   if(edges[0][0]*normal[1][0] < edges[4][0]*normal[2][0] + edges[3][0]*normal[3][0])
-//     return -1.0;
-
-//   double maxEdge = 0.0;
-//   for (int i=0; i<6; i++) {
-//     double l = vec_norm(edges[i]);
-//     if(l>maxEdge)
-//       maxEdge = l;
-//   }
-
-//   double minHeight = DBL_MAX; 
-//   for (int i=0; i<4; i++) {
-//     double h = vec_dot(edges[i], normal[i]);
-//     h = h*h/vec_norm(normal[i]);
-//     if(h<minHeight)
-//       minHeight = h;
-//   }
-
-//   return minHeight/maxEdge*1.5;
-// }
-
-
-// double myOwnAspectRatio(double a[3],  double b[3], double c[3], double d[3]) {
-//   double x[8], y[8], z[8];
-
-//   x[0] = b[0] - a[0];
-//   x[1] = c[0] - b[0];
-//   x[2] = d[0] - c[0];
-//   x[3] = a[0] - d[0];
-//   x[4] = c[0] - a[0];
-//   x[5] = d[0] - b[0];
-
-//   y[0] = b[1] - a[1];
-//   y[1] = c[1] - b[1];
-//   y[2] = d[1] - c[1];
-//   y[3] = a[1] - d[1];
-//   y[4] = c[1] - a[1];
-//   y[5] = d[1] - b[1];
-
-//   z[0] = b[2] - a[2];
-//   z[1] = c[2] - b[2];
-//   z[2] = d[2] - c[2];
-//   z[3] = a[2] - d[2];
-//   z[4] = c[2] - a[2];
-//   z[5] = d[2] - b[2];
-
-//   double normal_x[4], normal_y[4], normal_z[4];
-//   for (unsigned k=0; k<4; k++) {
-//     unsigned i = (k+1)&3;
-//     unsigned j = (k+2)&3;
-
-//     normal_x[k] = y[i]*z[j] - y[j]*z[i];
-//     normal_y[k] = z[i]*x[j] - z[j]*x[i];
-//     normal_z[k] = x[i]*y[j] - x[j]*y[i];
-//   }
-
-//   if(x[0]*normal_x[1] < x[4]*normal_x[2] + x[3]*normal_x[3])
-//     return -1.0;
-
-//   double maxEdge = 0.0;
-//   for (int i=0; i<6; i++) {
-//     double l = x[i]*x[i]+y[i]*y[i]+z[i]*z[i];
-//     if(l>maxEdge)
-//       maxEdge = l;
-//   }
-
-//   double minHeight = DBL_MAX; 
-//   for (int i=0; i<4; i++) {
-//     double h = x[i]*normal_x[i] + y[i]*normal_y[i] + z[i]*normal_z[i];
-//     double n = normal_x[i]*normal_x[i] + normal_y[i]*normal_y[i] + normal_z[i]*normal_z[i];
-//     h = h*h/n;
-//     if(h<minHeight)
-//       minHeight = h;
-//   }
-
-//   double r = minHeight/maxEdge;
-
-//   return r < (1./9.) ? r*4.5 : r*0.9 + 0.4;
-// }
-// #endif
\ No newline at end of file
diff --git a/contrib/hxt/hxt_tet_aspect_ratio.c b/contrib/hxt/hxt_tet_aspect_ratio.c
deleted file mode 100644
index 3320d5915d..0000000000
--- a/contrib/hxt/hxt_tet_aspect_ratio.c
+++ /dev/null
@@ -1,192 +0,0 @@
-#include <math.h>
-#include "predicates.h"
-
-void hxt_cross_prod(double a[3], double b[3], double c[3])
-{
-  c[2] = a[0] * b[1] - a[1] * b[0];
-  c[1] = -a[0] * b[2] + a[2] * b[0];
-  c[0] = a[1] * b[2] - a[2] * b[1];
-}
-
-double hxt_distance2(double p0[3], double p1[3]){
-  double a = p0[0]-p1[0];
-  double b = p0[1]-p1[1];
-  double c = p0[2]-p1[2];
-  return a*a+b*b+c*c;
-}
-
-double hxt_triangle_area(double p0[3], double p1[3], double p2[3])
-{
-  double a[3], b[3], c[3];
-
-  a[0] = p2[0] - p1[0];
-  a[1] = p2[1] - p1[1];
-  a[2] = p2[2] - p1[2];
-
-  b[0] = p0[0] - p1[0];
-  b[1] = p0[1] - p1[1];
-  b[2] = p0[2] - p1[2];
-
-  hxt_cross_prod(a, b, c);
-  return 0.5 * sqrt(c[0] * c[0] + c[1] * c[1] + c[2] * c[2]);
-}
-
-double hxtTetAspectRatio (double p0[3],  double p1[3], double p2[3], double p3[3]) {
-  double volume = orient3d (p0,p1,p2,p3) / 6.0;
-
-  double s1 = fabs(hxt_triangle_area(p0, p1, p2));
-  double s2 = fabs(hxt_triangle_area(p0, p2, p3));
-  double s3 = fabs(hxt_triangle_area(p0, p1, p3));
-  double s4 = fabs(hxt_triangle_area(p1, p2, p3));
-
-  double rhoin = 3. * volume / (s1 + s2 + s3 + s4);
-  double l  = hxt_distance2 (p0,p1);
-  double l2 = hxt_distance2 (p0,p2);
-  double l3 = hxt_distance2 (p0,p3);
-  double l4 = hxt_distance2 (p1,p2);
-  double l5 = hxt_distance2 (p1,p3);
-  double l6 = hxt_distance2 (p2,p3);
-
-  l = l2 > l ? l2:l;
-  l = l3 > l ? l3:l;
-  l = l4 > l ? l4:l;
-  l = l5 > l ? l5:l;
-  l = l6 > l ? l6:l;
-  
-  return sqrt(24./l) * rhoin ;
-}
-
-
-
-//!\ this function does not return the aspect ratio 'r'. It returns 'r^2/24'
-double hxtTetAspectFastRatio (double a[3],  double b[3], double c[3], double d[3]) {
-  double ab[3], ac[3], ad[3], bc[3], cd[3], db[3];
-  for (int i=0; i<3; i++) {
-    ab[i] = b[i] - a[i]; // AB
-    ac[i] = c[i] - a[i]; // AC
-    ad[i] = d[i] - a[i]; // AD
-  }
- 
-  double acxad0 = ac[1]*ad[2] - ac[2]*ad[1];
-  double adxab0 = ad[1]*ab[2] - ad[2]*ab[1];
-  double abxac0 = ab[1]*ac[2] - ab[2]*ac[1];
-  double volume6 = ab[0]*acxad0 + ac[0]*adxab0 + ad[0]*abxac0;
- 
-   // abort as early as possible
-  if(volume6<=0.0)
-    return 0.0;
- 
-  double acxad1 = ac[2]*ad[0] - ac[0]*ad[2];
-  double acxad2 = ac[0]*ad[1] - ac[1]*ad[0];
- 
-  double adxab1 = ad[2]*ab[0] - ad[0]*ab[2];
-  double adxab2 = ad[0]*ab[1] - ad[1]*ab[0];
- 
-  double abxac1 = ab[2]*ac[0] - ab[0]*ac[2];
-  double abxac2 = ab[0]*ac[1] - ab[1]*ac[0];
-
-  for (int i=0; i<3; i++) {
-    db[i] = b[i] - d[i]; // DB = B-D = AB-AD
-    bc[i] = c[i] - b[i]; // BC = C-B = AC-AB
-    cd[i] = d[i] - c[i]; // CD = D-c = AD-AC
-  }
- 
-  double bcxcd0 = bc[1]*cd[2] - bc[2]*cd[1]; // = acxad0+abxac0+adxab0;
-  double bcxcd1 = bc[2]*cd[0] - bc[0]*cd[2]; // = acxad1+abxac1+adxab1;
-  double bcxcd2 = bc[0]*cd[1] - bc[1]*cd[0]; // = acxad2+abxac2+adxab2;
-
-  double areaSum = sqrt(acxad0*acxad0 + acxad1*acxad1 + acxad2*acxad2)
-                 + sqrt(adxab0*adxab0 + adxab1*adxab1 + adxab2*adxab2)
-                 + sqrt(abxac0*abxac0 + abxac1*abxac1 + abxac2*abxac2)
-                 + sqrt(bcxcd0*bcxcd0 + bcxcd1*bcxcd1 + bcxcd2*bcxcd2);
-
-  double l = ab[0]*ab[0] + ab[1]*ab[1] + ab[2]*ab[2]; // |AB|²
-  double l2 = ac[0]*ac[0] + ac[1]*ac[1] + ac[2]*ac[2]; // |AC|²
-  double l3 = ad[0]*ad[0] + ad[1]*ad[1] + ad[2]*ad[2]; // |AD|²
-  double l4 = bc[0]*bc[0] + bc[1]*bc[1] + bc[2]*bc[2]; // |BC|²
-  double l5 = cd[0]*cd[0] + cd[1]*cd[1] + cd[2]*cd[2]; // |CD|²
-  double l6 = db[0]*db[0] + db[1]*db[1] + db[2]*db[2]; // |DB|²
-
-  if(l2>l) l=l2;
-  if(l3>l) l=l3;
-  if(l4>l) l=l4;
-  if(l5>l) l=l5;
-  if(l6>l) l=l6;
-
-  return volume6*volume6/(l*areaSum*areaSum);
-}
-
-
-// for a pair of tetrahedra: (abcd) and (abec)
-// void hxtTetAspectFastRatioPair (double a[3],  double b[3], double c[3], double d[3], double e[3], double* quality1, double quality2) {
-//   double ab[3], ac[3], ad[3], bc[3], cd[3], db[3];
-//   for (int i=0; i<3; i++) {
-//     ab[i] = b[i] - a[i]; // AB
-//     ac[i] = c[i] - a[i]; // AC
-//     ad[i] = d[i] - a[i]; // AD
-//     ae[i] = e[i] - a[i]; // AE
-//   }
- 
-//   double adxac0 = ad[1]*ac[2] - ad[2]*ac[1];
-//   double abxad0 = ab[1]*ad[2] - ab[2]*ad[1];
-//   double acxab0 = ac[1]*ab[2] - ac[2]*ab[1];
-//   double acxae0 = ac[1]*ae[2] - ac[2]*ae[1];
-//   double aexab0 = ae[1]*ab[2] - ae[2]*ab[1];
-//   double volume1 = ab[0]*adxac0 + ac[0]*abxad0 + ad[0]*acxab0;
-//   double volume2 = ab[0]*acxae0 - ae[0]*acxab0 + ac[0]*aexab0;
- 
-//    // abort as early as possible
-//   if(volume1<=0.0 || volume2<=0.0){
-//     *quality1 = 0.0;
-//     *quality2 = 0.0;
-//     return;
-//   }
- 
-//   double adxac1 = ad[2]*ac[0] - ad[0]*ac[2];
-//   double adxac2 = ad[0]*ac[1] - ad[1]*ac[0];
- 
-//   double abxad1 = ab[2]*ad[0] - ab[0]*ad[2];
-//   double abxad2 = ab[0]*ad[1] - ab[1]*ad[0];
- 
-//   double acxab1 = ac[2]*ab[0] - ac[0]*ab[2];
-//   double acxab2 = ac[0]*ab[1] - ac[1]*ab[0];
-
-//   double acxae1 = ac[2]*ae[0] - ac[0]*ae[2];
-//   double acxae2 = ac[0]*ae[1] - ac[1]*ae[0];
-
-//   double aexab1 = ae[2]*ab[0] - ae[0]*ab[2];
-//   double aexab2 = ae[0]*ab[1] - ae[1]*ab[0];
-
-//   for (int i=0; i<3; i++) {
-//     db[i] = b[i] - d[i]; // DB = B-D = AB-AD
-//     bc[i] = c[i] - b[i]; // BC = C-B = AC-AB
-//     cd[i] = d[i] - c[i]; // CD = D-c = AD-AC
-
-//   }
- 
-//   double cdxbc0 = cd[1]*bc[2] - cd[2]*bc[1]; // = adxac0+acxab0+abxad0;
-//   double cdxbc1 = cd[2]*bc[0] - cd[0]*bc[2]; // = adxac1+acxab1+abxad1;
-//   double cdxbc2 = cd[0]*bc[1] - cd[1]*bc[0]; // = adxac2+acxab2+abxad2;
-
-//   double commonArea = sqrt(acxab0*acxab0 + acxab1*acxab1 + acxab2*acxab2);
-
-//   double areaSum1 = commonArea
-//                   + sqrt(adxac0*adxac0 + adxac1*adxac1 + adxac2*adxac2)
-//                   + sqrt(abxad0*abxad0 + abxad1*abxad1 + abxad2*abxad2)
-//                   + sqrt(cdxbc0*cdxbc0 + cdxbc1*cdxbc1 + cdxbc2*cdxbc2);
-
-//   double l = ab[0]*ab[0] + ab[1]*ab[1] + ab[2]*ab[2]; // |AB|²
-//   double l2 = ac[0]*ac[0] + ac[1]*ac[1] + ac[2]*ac[2]; // |AC|²
-//   double l3 = ad[0]*ad[0] + ad[1]*ad[1] + ad[2]*ad[2]; // |AD|²
-//   double l4 = bc[0]*bc[0] + bc[1]*bc[1] + bc[2]*bc[2]; // |BC|²
-//   double l5 = cd[0]*cd[0] + cd[1]*cd[1] + cd[2]*cd[2]; // |CD|²
-//   double l6 = db[0]*db[0] + db[1]*db[1] + db[2]*db[2]; // |DB|²
-
-//   if(l2>l) l=l2;
-//   if(l3>l) l=l3;
-//   if(l4>l) l=l4;
-//   if(l5>l) l=l5;
-//   if(l6>l) l=l6;
-
-//   *quality1 = volume1*volume1/(l*areaSum1*areaSum1);
-// }
\ No newline at end of file
diff --git a/contrib/hxt/hxt_tet_aspect_ratio.h b/contrib/hxt/hxt_tet_aspect_ratio.h
deleted file mode 100644
index 0ecc2bd5f7..0000000000
--- a/contrib/hxt/hxt_tet_aspect_ratio.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _HXT_TET_ASPECT_RATIO_
-#define _HXT_TET_ASPECT_RATIO_
-
-double hxtTetAspectRatio (double p0[3],  double p1[3], double p2[3], double p3[3]);
-
-//!\ this function does not return the aspect ratio 'r'. It returns 'r^2/24'
-double hxtTetAspectFastRatio (double p0[3],  double p1[3], double p2[3], double p3[3]);
-
-#endif
diff --git a/contrib/hxt/hxt_tetrahedra.c b/contrib/hxt/hxt_tetrahedra.c
deleted file mode 100644
index b04c63369a..0000000000
--- a/contrib/hxt/hxt_tetrahedra.c
+++ /dev/null
@@ -1,1882 +0,0 @@
-#include "hxt_tetrahedra.h"
-#include "predicates.h"
-#include "hxt_tetRepair.h"
-#include "hxt_tetUtils.h"
-#include "hxt_tetFlag.h"
-#include "hxt_sort.h"
-
-/**
-* \file hxt_tetrahedra.c see header hxt_tetrahedra.h.
-* \author Célestin Marot
-*/
-
-/* compile-time parameters */
-#define SMALLEST_ROUND 2048
-#define DELETED_BUFFER_SIZE 8182
-// #define HXT_DELAUNAY_LOW_MEMORY /* doesn't use any buffer (a lot slower, except if you are at the limit of filling the RAM) */
-
-/* usefull macros */
-#define ABS(x) ((x) >= 0 ? (x) : -(x))
-#define MAX(x,y) ((x)>(y) ? (x) : (y))
-#define MIN(x,y) ((x)<(y) ? (x) : (y))
-
-#define HXT_OMP_CHECK(status) do{ HXTStatus _tmp_ = (status); \
-    if(_tmp_<0){ \
-      if(_tmp_>HXT_STATUS_INTERNAL) \
-        HXT_TRACE_MSG(_tmp_, "cannot break OpenMP region -> exiting"); \
-      fflush(stdout); fflush(stderr); \
-      exit(_tmp_); \
-    } \
-  }while(0)
-
-
-typedef struct{
-  uint32_t hxtDeclareAligned node[3];
-  uint16_t flag;
-  uint64_t neigh; // the tet on the other side of the boundar
-} cavityBnd_t;
-
-typedef struct {
-#ifndef HXT_DELAUNAY_LOW_MEMORY
-  uint64_t hxtDeclareAligned Map[1024];
-#endif
-
-  struct {
-    cavityBnd_t* bnd;
-    uint64_t num;
-    uint64_t size;
-  } ball;
-
-  struct {
-    uint64_t* tetID;
-    uint64_t num;
-    uint64_t size;
-  } deleted;
-
-  struct {
-    uint64_t startDist;
-    uint64_t endDist;
-    uint32_t first;
-  } partition;
-} TetLocal;
-
-
-/***********************************
- * create the initial tetrahedron 
- * surrounded by 4 ghost tetrahedra
- ***********************************/
-static inline HXTStatus hxtTetrahedraInit(HXTMesh* mesh, hxtNodeInfo* nodeInfo, uint32_t nToInsert, int verbosity){
-  if(nToInsert < 4){
-    return HXT_ERROR_MSG(HXT_STATUS_ERROR, "cannot mesh less than four vertices");
-  }
-  if(mesh->tetrahedra.size < 5){
-    uint32_t maxSizeEstim = MAX(omp_get_max_threads()*DELETED_BUFFER_SIZE+8UL*nToInsert, 10UL*nToInsert);
-    HXT_CHECK( hxtTetrahedraReserve(mesh, maxSizeEstim) );
-    HXT_INFO_COND(verbosity>1, "Initialization reserved %lu Tet.", mesh->tetrahedra.size);
-  }
-
-  HXTVertex* vertices = (HXTVertex*) mesh->vertices.coord;
-
-  // find non-coplanar vertices
-  double orientation = 0.0;
-
-  uint32_t i=0, j=1, k=2, l=3;
-  for (i=0; orientation==0.0 && i<nToInsert-3; i++)
-  {
-    for (j=i+1; orientation==0.0 && j<nToInsert-2; j++)
-    {
-      for (k=j+1; orientation==0.0 && k<nToInsert-1; k++)
-      {
-        for (l=k+1; orientation==0.0 && l<nToInsert; l++)
-        {
-          orientation = orient3d(vertices[nodeInfo[i].node].coord,
-                                 vertices[nodeInfo[j].node].coord,
-                                 vertices[nodeInfo[k].node].coord,
-                                 vertices[nodeInfo[l].node].coord);
-        }
-      }
-    }
-  }
-  l--; k--; j--; i--;
-
-
-  if(orientation==0.0){
-    return HXT_ERROR_MSG(HXT_STATUS_FAILED, "all vertices are coplanar");
-  }
-
-  // swap 0<->i  1<->j 2<->k 3<->l
-  {
-    hxtNodeInfo tmp = nodeInfo[i];
-    nodeInfo[i] = nodeInfo[0];
-    nodeInfo[0] = tmp;
-    nodeInfo[0].status = HXT_STATUS_TRUE;
-    i = 0;
-
-    tmp = nodeInfo[j];
-    nodeInfo[j] = nodeInfo[1];
-    nodeInfo[1] = tmp;
-    nodeInfo[1].status = HXT_STATUS_TRUE;
-    j = 1;
-
-    tmp = nodeInfo[k];
-    nodeInfo[k] = nodeInfo[2];
-    nodeInfo[2] = tmp;
-    nodeInfo[2].status = HXT_STATUS_TRUE;
-    k = 2;
-
-    tmp = nodeInfo[l];
-    nodeInfo[l] = nodeInfo[3];
-    nodeInfo[3] = tmp;
-    nodeInfo[3].status = HXT_STATUS_TRUE;
-    l = 3;
-  }
-
-
-  if(orientation < 0.0){
-    uint32_t tmp = i;
-    i = j;
-    j = tmp;
-  }
-
-  mesh->tetrahedra.neigh[ 0] = 19;    mesh->tetrahedra.node[ 0] = nodeInfo[l].node;
-  mesh->tetrahedra.neigh[ 1] = 15;    mesh->tetrahedra.node[ 1] = nodeInfo[k].node;
-  mesh->tetrahedra.neigh[ 2] = 11;    mesh->tetrahedra.node[ 2] = nodeInfo[j].node;
-  mesh->tetrahedra.neigh[ 3] =  7;    mesh->tetrahedra.node[ 3] = nodeInfo[i].node;
-
-  mesh->tetrahedra.neigh[ 4] = 18;    mesh->tetrahedra.node[ 4] = nodeInfo[l].node;
-  mesh->tetrahedra.neigh[ 5] = 10;    mesh->tetrahedra.node[ 5] = nodeInfo[j].node;
-  mesh->tetrahedra.neigh[ 6] = 13;    mesh->tetrahedra.node[ 6] = nodeInfo[k].node;
-  mesh->tetrahedra.neigh[ 7] =  3;    mesh->tetrahedra.node[ 7] = HXT_GHOST_VERTEX;
-
-  mesh->tetrahedra.neigh[8 ] = 17;    mesh->tetrahedra.node[ 8] = nodeInfo[l].node;
-  mesh->tetrahedra.neigh[9 ] = 14;    mesh->tetrahedra.node[ 9] = nodeInfo[k].node;
-  mesh->tetrahedra.neigh[10] =  5;    mesh->tetrahedra.node[10] = nodeInfo[i].node;
-  mesh->tetrahedra.neigh[11] =  2;    mesh->tetrahedra.node[11] = HXT_GHOST_VERTEX;
-
-  mesh->tetrahedra.neigh[12] = 16;    mesh->tetrahedra.node[12] = nodeInfo[l].node;
-  mesh->tetrahedra.neigh[13] =  6;    mesh->tetrahedra.node[13] = nodeInfo[i].node;
-  mesh->tetrahedra.neigh[14] =  9;    mesh->tetrahedra.node[14] = nodeInfo[j].node;
-  mesh->tetrahedra.neigh[15] =  1;    mesh->tetrahedra.node[15] = HXT_GHOST_VERTEX;
-
-  mesh->tetrahedra.neigh[16] = 12;    mesh->tetrahedra.node[16] = nodeInfo[k].node;
-  mesh->tetrahedra.neigh[17] =  8;    mesh->tetrahedra.node[17] = nodeInfo[j].node;
-  mesh->tetrahedra.neigh[18] =  4;    mesh->tetrahedra.node[18] = nodeInfo[i].node;
-  mesh->tetrahedra.neigh[19] =  0;    mesh->tetrahedra.node[19] = HXT_GHOST_VERTEX;
-
-  mesh->tetrahedra.num = 5;
-
-  for (uint64_t i=0; i<5 ;i++){
-    mesh->tetrahedra.colors[i] = UINT16_MAX;
-    mesh->tetrahedra.flag[i] = 0;
-  }
-
-  return HXT_STATUS_OK;
-}
-
-/***********************************
- * fill the passes array which tells
- * the size of each BRIO round.
- * return the number of BRIO passes
- ***********************************/
-static unsigned computePasses(uint32_t passes[12], uint32_t nInserted, uint32_t nToInsert)
-{
-  unsigned npasses=0;
-  passes[0] = nToInsert;
-
-  for (unsigned i=0; i<10; i++) {
-    if(passes[i] < SMALLEST_ROUND || passes[i]/8 < nInserted){
-      passes[i+1] = 0;
-      npasses = i+1;
-      break;
-    }
-    passes[i+1] = passes[i]/7.5;
-  }
-
-  for(unsigned i=0; i<=npasses/2; i++){
-    uint32_t tmp = passes[i];
-    passes[i] = passes[npasses-i];
-    passes[npasses-i] = tmp;
-  }
-
-  return npasses;
-}
-
-/******************************************
- * initialisation of the TetLocal structure
- ******************************************/
-static inline HXTStatus localInit(TetLocal* local){
-    local->ball.size = 1020; // accounting for the offset in aligned malloc, to avoid additional memory page
-    local->ball.num = 0;
-    local->ball.bnd = NULL;
-    local->deleted.size = DELETED_BUFFER_SIZE;
-    local->deleted.num = 0;
-    local->deleted.tetID = NULL;
-
-    HXT_CHECK( hxtAlignedMalloc(&local->ball.bnd, local->ball.size*sizeof(cavityBnd_t)) );
-    HXT_CHECK( hxtAlignedMalloc(&local->deleted.tetID, local->deleted.size*sizeof(uint64_t)) );
-
-    return HXT_STATUS_OK;
-}
-
-/***********************************************
-           re-allocation functions
- ***********************************************/
-static HXTStatus synchronizeReallocation(HXTMesh* mesh, volatile int* toCopy, volatile int* copy){
-  // threads cant be doing something while the realloc portion happen
-  #pragma omp barrier
-  
-  // this unable us to have the same value of toCopy for everyone, as we are sure nothing happens to those variables here
-  if(toCopy!=copy){
-    *copy = *toCopy;
-  }
-
-  HXTStatus status = HXT_STATUS_OK;
-  // make reallocations in a critical section
-  #pragma omp single
-  {
-    if(mesh->tetrahedra.num > mesh->tetrahedra.size){
-      status = hxtTetrahedraDoubleSize(mesh);
-    }
-  } // implicit barrier here
-
-  if(status!=HXT_STATUS_OK)
-    HXT_TRACE(status);
-
-  return status;
-}
-
-
-// pragma atomic capture to get tetrahedra.num and update it at the same time before caling this function !
-static inline HXTStatus reserveNewTet(HXTMesh* mesh){
-  if(mesh->tetrahedra.num > mesh->tetrahedra.size){
-    HXT_CHECK( synchronizeReallocation(mesh, NULL, NULL) );
-  }
-
-  return HXT_STATUS_OK;
-}
-
-static inline HXTStatus reserveNewDeleted(TetLocal* local, uint64_t num){
-  num += local->deleted.num;
-  if(num > local->deleted.size){
-      HXT_CHECK( hxtAlignedRealloc(&local->deleted.tetID, 2*num*sizeof(uint64_t)) );
-      local->deleted.size = 2*num;
-  }
-
-  return HXT_STATUS_OK;
-}
-
-static inline HXTStatus reserveNewBnd(TetLocal* local, uint64_t num){
-  num += local->ball.num;
-  if(num > local->ball.size){
-      HXT_CHECK( hxtAlignedRealloc(&local->ball.bnd, 2*num*sizeof(cavityBnd_t)) );
-      local->ball.size = 2*num;
-  }
-
-  return HXT_STATUS_OK;
-}
-/***********************************************/
-
-/************************************
- * check if a tetrahedra is entirely
- * in the calling thread's partition
- ***********************************/
-static inline HXTStatus checkTetrahedron(HXTVertex* vertices, TetLocal* local, const uint32_t* nodes){
-  /* Actually, one vertex (not more) could be in another partition without creating a conflict.
-   However, all threads would have to have a verticesID array => a lot of memory space wasted.
-   Instead, we only allow the ghost vertex to be in another partition, it is handle differently in
-   computeAdjacenciesFast function */
-  uint64_t rel = local->partition.endDist - local->partition.startDist;
-
-  if(local->partition.endDist==UINT64_MAX) // if we are working with one thread only
-    return HXT_STATUS_OK;
-
-  // unsigned wrap around is defined by the standard
-  uint64_t d0 = vertices[nodes[0]].padding.hilbertDist - local->partition.startDist;
-  uint64_t d1 = vertices[nodes[1]].padding.hilbertDist - local->partition.startDist;
-  uint64_t d2 = vertices[nodes[2]].padding.hilbertDist - local->partition.startDist;
-  uint64_t d3 = nodes[3]==HXT_GHOST_VERTEX ? d2: (vertices[nodes[3]].padding.hilbertDist - local->partition.startDist);
-  
-  if((d0>=rel) || (d1>=rel) || (d2>=rel) || (d3>=rel))
-    return HXT_STATUS_INTERNAL;
-
-  return HXT_STATUS_OK;
-
-}
-
-
-static inline HXTStatus pointIsTooClose(const double* __restrict__ p1, const double* __restrict__ p2, double nodalSize){
-  double d2 = (p1[0]-p2[0])*(p1[0]-p2[0])
-            + (p1[1]-p2[1])*(p1[1]-p2[1])
-            + (p1[2]-p2[2])*(p1[2]-p2[2]); 
-  if (d2 < 0.8*0.8*nodalSize*nodalSize){
-    return  HXT_STATUS_INTERNAL;
-  }
-
-  return HXT_STATUS_OK;
-}
-
-/* if one edge of the cavity is shorter than the nodalSize, return HXT_STATUS_INTERNAL */
-static inline HXTStatus filterCavity (TetLocal* local, HXTMesh *mesh, const double *nodalSizes, const uint32_t vta)
-{
-  double *vtaCoord = mesh->vertices.coord + 4*vta;
-  double vtaNodalSize = nodalSizes[vta];
-
-  for (uint64_t i = 0 ; i< local->ball.num ; i++) {
-    for (unsigned j=0;j<3;j++) {
-      uint32_t nodej = local->ball.bnd[i].node[j];
-
-      if (j!=3 || nodej != HXT_GHOST_VERTEX){
-        double *Xj = mesh->vertices.coord + 4*nodej;
-        HXT_CHECK( pointIsTooClose(vtaCoord, Xj, 0.5*( vtaNodalSize + nodalSizes[nodej])) );
-      }
-    }
-  }
-  return  HXT_STATUS_OK;
-}
-
-static inline HXTStatus filterTet(HXTMesh* mesh, const double *nodalSizes, const uint64_t curTet, const uint32_t vta){
-  HXTVertex* vertices = (HXTVertex*) mesh->vertices.coord;
-
-  double *vtaCoord = vertices[vta].coord;
-  double vtaNodalSize = nodalSizes[vta];
-
-  for (unsigned j=0; j<4; j++) {
-    uint32_t nodej = mesh->tetrahedra.node[4*curTet+j];
-
-    if (j!=3 || nodej != HXT_GHOST_VERTEX){
-      double* Xj = vertices[nodej].coord;
-      double otherNodalSize = nodalSizes[nodej];
-      if(otherNodalSize==DBL_MAX){
-        otherNodalSize = vtaNodalSize;
-      }
-      HXT_CHECK( pointIsTooClose(vtaCoord, Xj, 0.5*( vtaNodalSize + otherNodalSize)) );
-    }
-  }
-  return HXT_STATUS_OK;
-}
-
-
-/* restore the structure as it was before the failed insertion attempt */
-static inline void restoreDeleted(HXTMesh* mesh, TetLocal* local, const uint64_t prevDeleted, const uint16_t color){
-  for (uint64_t i=prevDeleted; i<local->deleted.num; i++)
-    unmarkTetAsDeleted(mesh, local->deleted.tetID[i]);
-
-  local->deleted.num = prevDeleted;
-}
-
-
-/***********************************
- * insphere predicate & perturbation
- ***********************************/
-// see Perturbations and Vertex Removal in a 3D Delaunay Triangulation, O. Devillers & M. Teillaud
-static double symbolicPerturbation (uint32_t indices[5] ,  const double* __restrict__ i,
-                                                           const double* __restrict__ j,
-                                                           const double* __restrict__ k,
-                                                           const double* __restrict__ l,
-                                                           const double* __restrict__ m){
-  double const* pt[5] = {i,j,k,l,m};
-
-  // Sort the five points such that their indices are in the increasing
-  //   order. An optimized bubble sort algorithm is used, i.e., it has
-  //   the worst case O(n^2) runtime, but it is usually much faster.
-  int swaps = 0; // Record the total number of swaps.
-  int n = 5;
-  int count;
-  do {
-    count = 0;
-    n = n - 1;
-    for (int iter = 0; iter < n; iter++) {
-      if (indices[iter] > indices[iter+1]) {
-
-        const double *swappt = pt[iter];
-        pt[iter] = pt[iter+1];
-        pt[iter+1] = swappt;
-
-        uint32_t sw = indices [iter];
-        indices[iter] = indices[iter+1];
-        indices[iter+1] = sw;
-        count++;
-      }
-    }
-    swaps += count;
-  } while (count > 0); // Continue if some points are swapped.
-  
-  double oriA = orient3d(pt[1], pt[2], pt[3], pt[4]);
-  if (oriA != 0.0) {
-    // Flip the sign if there are odd number of swaps.
-    if ((swaps % 2) != 0) oriA = -oriA;
-    return oriA;
-  }
-  
-  double oriB = -orient3d(pt[0], pt[2], pt[3], pt[4]);
-  if (oriB == 0.0) HXT_WARNING("Symbolic perturbation failed (2 superposed vertices ?)");
-
-  // Flip the sign if there are odd number of swaps.
-  if ((swaps % 2) != 0) oriB = -oriB;
-  return oriB;
-}
-
-
-/* wrapper around the insphere predicate that handles
-   the ghost vertex and symbolic perturbation if needed */
-double tetInsphere(HXTMesh* mesh, const uint64_t curTet, const uint32_t vta){
-  HXTVertex* vertices = (HXTVertex*) mesh->vertices.coord;
-  uint32_t* Node = mesh->tetrahedra.node + curTet;
-
-  const double* __restrict__ a = vertices[Node[0]].coord;
-  const double* __restrict__ b = vertices[Node[1]].coord;
-  const double* __restrict__ c = vertices[Node[2]].coord;
-  const double* __restrict__ e = vertices[vta].coord;
-
-  if(Node[3]==HXT_GHOST_VERTEX){ 
-    double det = orient3d(a,b,c,e);
-
-    if(det!=0.0){
-      return det;
-    }
-
-    // we never go here, except when point are aligned on boundary
-    // HXT_INFO("insphere using opposite vertex");
-    uint32_t oppositeNode = mesh->tetrahedra.node[mesh->tetrahedra.neigh[curTet+3]];
-    double* const __restrict__ oppositeVertex = vertices[oppositeNode].coord;
-    det = insphere(a,b,c,oppositeVertex,e);
-
-    if (det == 0.0) {
-      uint32_t nn[5] = {Node[0],Node[1],Node[2],oppositeNode,vta};
-      // HXT_INFO("symbolic perturbation on boundary");
-      det = symbolicPerturbation (nn, a,b,c,oppositeVertex,e);
-      
-    }
-    return -det;
-  }
-
-  double* const __restrict__ d = vertices[Node[3]].coord;
-
-  double det = insphere(a,b,c,d,e);
-  if (det == 0.0) {
-    uint32_t nn[5] = {Node[0],Node[1],Node[2],Node[3],vta};
-    // HXT_INFO("symbolic perturbation");
-    det = symbolicPerturbation (nn, a,b,c,d,e);
-  }
-  return det;
-}
-
-
-/***********************************
- * walk to cavity
- ***********************************/
-static HXTStatus walking2Cavity(HXTMesh* mesh, TetLocal* local, uint64_t* __restrict__ curTet, const uint32_t vta){
-  uint64_t nextTet = *curTet;
-  uint32_t seed = 1;
-  HXTVertex* vertices = (HXTVertex*) mesh->vertices.coord;
-
-  /* if nextTet is a ghost triangle, go to the neighbor that is not a ghost triangle */
-  if(mesh->tetrahedra.node[4*nextTet+3]==HXT_GHOST_VERTEX)
-    nextTet = mesh->tetrahedra.neigh[4*nextTet+3]/4;
-
-  double* const vtaCoord = vertices[vta].coord;
-  unsigned enteringFace = 4;
-
-#ifndef NDEBUG
-  uint64_t TotalCount = 0;
-#endif
-  
-
-  while(1){
-    const uint32_t* __restrict__ curNode = mesh->tetrahedra.node + 4*nextTet;
-    const uint64_t* __restrict__ curNeigh = mesh->tetrahedra.neigh + 4*nextTet;
-
-  #ifndef NDEBUG
-    if(curNode[3]==HXT_GHOST_VERTEX){
-      return HXT_ERROR_MSG(HXT_STATUS_FAILED, "walked outside of the domain");
-    }
-  #endif
-
-    unsigned neigh = 4;
-    unsigned outside = 0;
-    uint32_t randomU = hxtReproducibleLCG(&seed);
-    for (unsigned i=0; i<4; i++)
-    {
-      uint32_t index = (i+randomU)%4;
-      if (index!=enteringFace) {
-        // we walk where the volume is minimum
-        const double* __restrict__ a = vertices[curNode[(index+1)&3]].coord;
-        const double* __restrict__ b = vertices[curNode[(index&2)^3]].coord;
-        const double* __restrict__ c = vertices[curNode[(index+3)&2]].coord;
-
-        if (orient3d(a,b,c, vtaCoord) < 0.0){
-          if(curNeigh[index]==HXT_NO_ADJACENT) { // the point is outside the triangulation
-            return HXT_ERROR_MSG(HXT_STATUS_ERROR,
-                                "vertex {%f %f %f} outside the triangulation and no ghost tetrahedra",
-                                 vtaCoord[0], vtaCoord[1], vtaCoord[2]);
-          }
-
-          uint64_t tet = curNeigh[index]/4;
-          const uint32_t* __restrict__ neighNodes = mesh->tetrahedra.node + tet*4;
-          if(checkTetrahedron(vertices, local, neighNodes)==HXT_STATUS_OK){
-            if(neighNodes[3]==HXT_GHOST_VERTEX){
-              *curTet = tet;
-              return HXT_STATUS_OK;
-            }
-            neigh=index;
-            break;
-          }
-          outside = 1;
-        }
-      }
-    }
-
-    if(neigh==4){
-      const double* __restrict__ a = vertices[curNode[0]].coord;
-      const double* __restrict__ b = vertices[curNode[1]].coord;
-      const double* __restrict__ c = vertices[curNode[2]].coord;
-      const double* __restrict__ d = vertices[curNode[3]].coord;
-      if(outside ||
-         (orient3d(a,b,c,vtaCoord)<=0.0) +
-         (orient3d(a,b,vtaCoord,d)<=0.0) +
-         (orient3d(a,vtaCoord,c,d)<=0.0) +
-         (orient3d(vtaCoord,b,c,d)<=0.0)>2){
-        return HXT_STATUS_TRYAGAIN;
-      }
-      *curTet = nextTet;
-      return HXT_STATUS_OK;
-    }
-
-    //    printf("nextTet %u %g %u %u\n",nextTet,Min, count, neigh);
-    nextTet = curNeigh[neigh]/4;
-    enteringFace = curNeigh[neigh]&3;
-
-  #ifndef NDEBUG
-    if(TotalCount>mesh->tetrahedra.num){
-      return HXT_ERROR_MSG(HXT_STATUS_FAILED, "infinite walk to find the cavity");
-    }
-    // printf("%lu\n",TotalCount);
-    TotalCount++;
-  #endif
-  }
-}
-
-
-/***********************************
- * digging cavity
- ***********************************/
-
-/* pushing cavity boundary information to local->ball */
-static inline void bndPush( TetLocal* local, uint16_t flag,
-              const uint32_t node1, const uint32_t node2,
-              const uint32_t node3, const uint64_t neigh){
-  uint64_t n = local->ball.num;
-  local->ball.bnd[n].node[0] = node1;
-  local->ball.bnd[n].node[1] = node2;
-  local->ball.bnd[n].node[2] = node3;
-  local->ball.bnd[n].flag = flag;
-  local->ball.bnd[n].neigh = neigh;
-  local->ball.num++;
-}
-
-/* delete a tetrahedra being part of the cavity */
-static inline HXTStatus deletedPush(HXTMesh* mesh, TetLocal* local, const uint64_t neigh){
-  // check if 3 points of the new tetrahedra are owned by this thread
-  HXT_CHECK( checkTetrahedron((HXTVertex*) mesh->vertices.coord, local, mesh->tetrahedra.node + neigh*4) );
-  local->deleted.tetID[local->deleted.num++] = neigh;
-  markTetAsDeleted(mesh, neigh);
-
-  return HXT_STATUS_OK;
-}
-
-/* check if the cavity is star shaped
-   This isn't usefull for pure Delaunay but when we constrain cavity with colors,
-   it is usefull */
-static HXTStatus isStarShaped(TetLocal* local, HXTMesh* mesh, const uint32_t vta, uint64_t* blindFaceIndex)
-{
-  HXTVertex* vertices = (HXTVertex*) mesh->vertices.coord;
-  double *vtaCoord = vertices[vta].coord;
-
-  for (uint64_t i=0; i<local->ball.num; i++) {
-    if(local->ball.bnd[i].node[2]==HXT_GHOST_VERTEX){
-
-    }
-    else{
-      double* b = vertices[local->ball.bnd[i].node[0]].coord;
-      double* c = vertices[local->ball.bnd[i].node[1]].coord;
-      double* d = vertices[local->ball.bnd[i].node[2]].coord;
-      if(orient3d(vtaCoord, b, c, d)<=0.0){
-        *blindFaceIndex = i;
-        return HXT_STATUS_INTERNAL;
-      }
-    }
-  }
-  return HXT_STATUS_OK;
-}
-
-
-static HXTStatus undeleteTetrahedron(TetLocal* local, HXTMesh* mesh, const uint32_t vta, uint64_t tetToUndelete) {
-  // the tetrahedra should not be deleted anymore
-  for (uint64_t i=local->deleted.num; ; i--) {
-    if(local->deleted.tetID[i-1]==tetToUndelete) {
-      local->deleted.num--;
-      local->deleted.tetID[i-1] = local->deleted.tetID[local->deleted.num];
-      break;
-    }
-#ifdef DEBUG
-    if(i==1)
-      return HXT_ERROR_MSG(HXT_STATUS_ERROR, "could not find the tetrahedra in the deleted array");
-#endif
-  }
-  unmarkTetAsDeleted(mesh, tetToUndelete);
-
-  uint64_t bndFaces[4] = {HXT_NO_ADJACENT, HXT_NO_ADJACENT, HXT_NO_ADJACENT, HXT_NO_ADJACENT};
-  int nbndFace = 0;
-
-  // we should update the boundary (that's the difficult part...)
-  // first remove all the boundary faces that come from the tetrahedron we just remove from the cavity
-  for (uint64_t i=local->ball.num; nbndFace<4 && i>0; i--) {
-    if(mesh->tetrahedra.neigh[local->ball.bnd[i-1].neigh]/4==tetToUndelete) {
-      bndFaces[nbndFace++] = local->ball.bnd[i-1].neigh;
-      local->ball.num--;
-      local->ball.bnd[i-1] = local->ball.bnd[local->ball.num];
-    }
-  }
-
-  // we must replace them by all the other faces of the tetrahedron we just removed
-  const uint64_t* __restrict__ curNeigh = mesh->tetrahedra.neigh + tetToUndelete*4;
-  const uint32_t* __restrict__ curNode = mesh->tetrahedra.node + tetToUndelete*4;
-
-#ifdef DEBUG
-  int nbndFace2 = (isTetDeleted(mesh, curNeigh[0]/4)==0) + (isTetDeleted(mesh, curNeigh[1]/4)==0) + (isTetDeleted(mesh, curNeigh[2]/4)==0) + (isTetDeleted(mesh, curNeigh[3]/4)==0);
-  if(nbndFace!=nbndFace2)
-    return HXT_ERROR_MSG(HXT_STATUS_ERROR, "found %d non-deleted tet adjacent to the tet we unremove but there should be %d %lu %lu %lu %lu", nbndFace, nbndFace2, bndFaces[0], bndFaces[1], bndFaces[2], bndFaces[3]);
-#endif
-
-  HXT_CHECK( reserveNewBnd(local, 3) );
-
-  if(curNeigh[0]!=bndFaces[0] && curNeigh[0]!=bndFaces[1] && curNeigh[0]!=bndFaces[2] && curNeigh[0]!=bndFaces[3])
-    bndPush(local,  (mesh->tetrahedra.flag[tetToUndelete] & 0x9) | 
-                    (isEdgeConstrained(mesh, tetToUndelete, 0 , 2)>>1) |
-                    (isEdgeConstrained(mesh, tetToUndelete, 0 , 1)<<1), curNode[2], curNode[1], curNode[3], 4*tetToUndelete+0);
-
-  if(curNeigh[1]!=bndFaces[0] && curNeigh[1]!=bndFaces[1] && curNeigh[1]!=bndFaces[2] && curNeigh[1]!=bndFaces[3])
-    bndPush(local,  ((mesh->tetrahedra.flag[tetToUndelete] & 0xD0)>>4) | 
-                    isEdgeConstrained(mesh, tetToUndelete, 0 , 1), curNode[0], curNode[2], curNode[3], 4*tetToUndelete+1);
-
-  if(curNeigh[2]!=bndFaces[0] && curNeigh[2]!=bndFaces[1] && curNeigh[2]!=bndFaces[2] && curNeigh[2]!=bndFaces[3])
-    bndPush(local,  ((mesh->tetrahedra.flag[tetToUndelete] & 0x900)>>8) | 
-                    (isEdgeConstrained(mesh, tetToUndelete, 1 , 2)>>5) |
-                     isEdgeConstrained(mesh, tetToUndelete, 0 , 2), curNode[1], curNode[0], curNode[3], 4*tetToUndelete+2);
-
-  if(curNeigh[3]!=bndFaces[0] && curNeigh[3]!=bndFaces[1] && curNeigh[3]!=bndFaces[2] && curNeigh[3]!=bndFaces[3])
-    bndPush(local, (isFacetConstrained(mesh, 4*tetToUndelete+3)>>12) | 
-                   (isEdgeConstrained(mesh, tetToUndelete, 0 , 3)>>2) |
-                   (isEdgeConstrained(mesh, tetToUndelete, 1 , 3)>>5) |
-                   (isEdgeConstrained(mesh, tetToUndelete, 2 , 3)>>8), curNode[0], curNode[1], curNode[2], 4*tetToUndelete+3);
-
-  return HXT_STATUS_OK;
-}
-
-
-static HXTStatus reshapeCavityIfNeeded(TetLocal* local, HXTMesh* mesh, const uint32_t vta, uint64_t prevDeleted) {
-  // we will remove the tetrahedra adjacent to the face that does not see the point, progressively, until the cavity is star shaped...
-  uint64_t blindFace = 0;
-  while(isStarShaped(local, mesh, vta, &blindFace)==HXT_STATUS_INTERNAL)
-  {
-    // printf("deleting %lu  cavity:%lu  ball:%lu\n",mesh->tetrahedra.neigh[local->ball.bnd[blindFace].neigh]/4, local->deleted.num-prevDeleted, local->ball.num );
-    HXT_CHECK( undeleteTetrahedron(local, mesh, vta, mesh->tetrahedra.neigh[local->ball.bnd[blindFace].neigh]/4) );
-  }
-  return HXT_STATUS_OK;
-}
-
-
-static HXTStatus respectEdgeConstraint(TetLocal* local, HXTMesh* mesh, const uint32_t vta, const uint16_t color, const uint64_t prevDeleted) {
-  // HXT_WARNING("a constrained edge was inside the cavity, recovering it");
-
-  // all the tetrahedron have the same color 'color', we will use that color to flag them
-  for (uint64_t i=prevDeleted; i<local->deleted.num; i++) {
-    uint64_t delTet = local->deleted.tetID[i];
-    mesh->tetrahedra.colors[delTet] = 0;
-  }
-
-  for (uint64_t i=prevDeleted; i<local->deleted.num; i++) {
-    uint64_t delTet = local->deleted.tetID[i];
-    int exist = 1;
-    for (int j=0; exist && j<4; j++) {
-      for (int k=j+1; exist && k<4; k++) {
-        if(isEdgeConstrained(mesh, delTet, j, k) && (mesh->tetrahedra.colors[delTet] & (1U<<(j*4+k)))==0) {
-          // const int _UP_FACET[4][4] = {{-1, 2, 3, 1},
-          //                              { 3,-1, 0, 2},
-          //                              { 1, 3,-1, 0},
-          //                              { 2, 0, 1,-1}};
-
-          // HXT_WARNING("found constrained edge %u-%u in tetrahedron %lu (%d %d) inside the cavity\n",mesh->tetrahedra.node[4*delTet+ _UP_FACET[j][k]], mesh->tetrahedra.node[4*delTet+ _UP_FACET[k][j]], delTet, j, k);
-          // turn around the edge to check if a facet is on the boundary of the cavity. If yes, the edge is processed... if not, we delete one tet.
-          int in_facet = j;
-          int out_facet = k;
-
-          int edgeIsSafe = 0;
-          uint64_t curTet = delTet;
-          // first turn
-          do
-          {
-            uint32_t newV = mesh->tetrahedra.node[4*curTet + in_facet];
-
-            // go into the neighbor through out_facet
-            uint64_t neigh = mesh->tetrahedra.neigh[4*curTet + out_facet];
-            curTet = neigh/4;
-            in_facet = neigh%4;
-
-            uint32_t* nodes = mesh->tetrahedra.node + 4*curTet;
-            for (out_facet=0; out_facet<3; out_facet++)
-              if(nodes[out_facet]==newV)
-                break;
-
-            if(isTetDeleted(mesh, curTet)!=0) {
-              // mark that the edge as been treate
-              #ifdef DEBUG
-                if((mesh->tetrahedra.colors[curTet] & (1U<<(in_facet<out_facet?in_facet*4+out_facet:out_facet*4+in_facet)))!=0)
-                  return HXT_ERROR_MSG(HXT_STATUS_ERROR, "the flag says that the tet has already been processed for this edge...");
-              #endif
-              mesh->tetrahedra.colors[curTet] |= (1U<<(in_facet*4+out_facet)) | (1U<<(out_facet*4+in_facet));
-            }
-            else {
-              edgeIsSafe=1;
-            }
-
-            // printf("edge %u-%u, tet %lu (%d %d)  deleted:%u\n", mesh->tetrahedra.node[4*curTet+ _UP_FACET[in_facet][out_facet]], mesh->tetrahedra.node[4*curTet+ _UP_FACET[out_facet][in_facet]], curTet, in_facet, out_facet, isTetDeleted(mesh, curTet)!=0);
-
-          } while (curTet!=delTet);
-
-          if(!edgeIsSafe) { // we must find a tetrahedron on the opposite side of vta and delete it.
-            in_facet = j;
-            out_facet = k;
-            curTet = delTet;
-
-            uint64_t tetContainingVta = local->deleted.tetID[prevDeleted];
-            uint64_t tetToUndelete = HXT_NO_ADJACENT;
-            double distMax = 0.0;
-            double* vtaCoord = mesh->vertices.coord + 4*vta;
-
-          #ifdef DEBUG
-            double* a = mesh->vertices.coord + 4*mesh->tetrahedra.node[4*tetContainingVta];
-            double* b = mesh->vertices.coord + 4*mesh->tetrahedra.node[4*tetContainingVta+1];
-            double* c = mesh->vertices.coord + 4*mesh->tetrahedra.node[4*tetContainingVta+2];
-            double* d = mesh->vertices.coord + 4*mesh->tetrahedra.node[4*tetContainingVta+3];
-
-            if(orient3d(vtaCoord,b,c,d)<0.0 || orient3d(a,vtaCoord,c,d)<0.0 || orient3d(a,b,vtaCoord,d)<0.0 || orient3d(a,b,c,vtaCoord)<0.0) {
-              return HXT_ERROR_MSG(HXT_STATUS_ERROR, "an edge part of a ghost tetrahedron is constrained");
-            }
-          #endif
-
-            do
-            {
-              uint32_t newV = mesh->tetrahedra.node[4*curTet + in_facet];
-
-              // go into the neighbor through out_facet
-              uint64_t neigh = mesh->tetrahedra.neigh[4*curTet + out_facet];
-              curTet = neigh/4;
-              in_facet = neigh%4;
-
-              uint32_t* nodes = mesh->tetrahedra.node + 4*curTet;
-              for (out_facet=0; out_facet<3; out_facet++)
-                if(nodes[out_facet]==newV)
-                  break;
-
-              double* coord1 = mesh->vertices.coord + newV;
-              double* coord2 = mesh->vertices.coord + nodes[in_facet];
-
-              if(curTet!=tetContainingVta) {
-                double dist = 0.0;
-                for (int l=0; l<3; l++) {
-                  double meanCoord = (coord1[l]+coord2[l])*0.5;
-                  double diff = meanCoord-vtaCoord[l];
-                  dist += diff*diff;
-                }
-
-                if(dist>distMax) {
-                  dist = distMax;
-                  tetToUndelete = curTet;
-                }
-              }
-            } while (curTet!=delTet);
-
-            if(tetToUndelete==delTet)
-              exist = 0;
-
-            // printf("undeleting tetrahedron %lu\n", tetToUndelete);
-            mesh->tetrahedra.colors[tetToUndelete] = color;
-            HXT_CHECK( undeleteTetrahedron(local, mesh, vta, tetToUndelete) );
-          }
-        }
-      }
-    }
-  }
-
-  for (uint64_t i=prevDeleted; i<local->deleted.num; i++) {
-    uint64_t delTet = local->deleted.tetID[i];
-    mesh->tetrahedra.colors[delTet] = color;
-  }
-
-  return HXT_STATUS_OK;
-}
-
-
-/* this function does a Breadth-first search of the tetrahedra in the cavity
- * it add those to local->deleted
- * it also maintain a local->bnd array with all the information concerning the boundary of the cavity
- */
-static inline HXTStatus diggingACavity(HXTMesh* mesh, TetLocal* local, uint64_t curTet, const uint32_t vta, int* edgeConstraint){
-  // add tetrahedra to cavity
-  local->deleted.tetID[local->deleted.num++] = curTet;
-  markTetAsDeleted(mesh, curTet);
-  local->ball.num = 0;
-
-  
-
-  for(uint64_t start=local->deleted.num-1; start < local->deleted.num; start++){
-    uint64_t curTet = local->deleted.tetID[start];
-    const uint64_t* __restrict__ curNeigh = mesh->tetrahedra.neigh + 4*curTet;
-    const uint32_t* __restrict__ curNode = mesh->tetrahedra.node + 4*curTet;
-
-    *edgeConstraint += isAnyEdgeConstrained(mesh, curTet)!=0;
-
-    /* here we allocate enough space for the boundary (local->bnd), the cavity (local->deleted) and the vertices (local->vertices) */
-    HXT_CHECK( reserveNewDeleted(local, 4) );
-    HXT_CHECK( reserveNewBnd(local, 4) );
-
-    // we unrolled the loop for speed (also because indices are not trivial, we would need a 4X4 array)
-
-    /* and here we push stuff to local->bnd or local->deleted, always keeping ghost tet at last place */
-    uint64_t neigh = curNeigh[0]/4;
-    if(curNeigh[0]!=HXT_NO_ADJACENT && isTetDeleted(mesh, neigh)==0){
-      if(isFacetConstrained(mesh, 4*curTet+0) || 
-        tetInsphere(mesh, neigh*4, vta)<=0.0){
-        bndPush(local, mesh->tetrahedra.flag[curTet] & 0xF,
-                       curNode[1], curNode[2], curNode[3], curNeigh[0]);
-      }
-      else{
-        HXT_CHECK( deletedPush(mesh, local, neigh) );
-      }
-    }
-
-    neigh = curNeigh[1]/4;
-    if(curNeigh[1]!=HXT_NO_ADJACENT && isTetDeleted(mesh, neigh)==0){
-      if(isFacetConstrained(mesh, 4*curTet+1) || 
-        tetInsphere(mesh, neigh*4, vta)<=0.0){
-        bndPush(local, (isFacetConstrained(mesh, 4*curTet+1)>>4) | 
-                       (isEdgeConstrained(mesh, curTet, 1 , 2)>>5) |
-                       (isEdgeConstrained(mesh, curTet, 0 , 1)<<1) |
-                       (isEdgeConstrained(mesh, curTet, 1 , 3)>>4),
-                       curNode[2], curNode[0], curNode[3], curNeigh[1]);
-      }
-      else{
-        HXT_CHECK( deletedPush(mesh, local, neigh) );
-      }
-    }
-
-    neigh = curNeigh[2]/4;
-    if(curNeigh[2]!=HXT_NO_ADJACENT && isTetDeleted(mesh, neigh)==0){
-      if(isFacetConstrained(mesh, 4*curTet+2)|| 
-        tetInsphere(mesh, neigh*4, vta)<=0.0){
-        bndPush(local, (isFacetConstrained(mesh, 4*curTet+2)>>8) | 
-                       (isEdgeConstrained(mesh, curTet, 0 , 2)>>1) |
-                       (isEdgeConstrained(mesh, curTet, 1 , 2)>>4) |
-                       (isEdgeConstrained(mesh, curTet, 2 , 3)>>8),
-                       curNode[0], curNode[1], curNode[3], curNeigh[2]);
-      }
-      else{
-        HXT_CHECK( deletedPush(mesh, local, neigh) );
-      }
-    }
-
-    neigh = curNeigh[3]/4;
-    if(curNeigh[3]!=HXT_NO_ADJACENT && isTetDeleted(mesh, neigh)==0){
-      if(isFacetConstrained(mesh, 4*curTet+3) || 
-        tetInsphere(mesh, neigh*4, vta)<=0.0){
-        
-        bndPush(local, (isFacetConstrained(mesh, 4*curTet+3)>>12) | 
-                       (isEdgeConstrained(mesh, curTet, 1 , 3)>>6) |
-                       (isEdgeConstrained(mesh, curTet, 0 , 3)>>1) |
-                       (isEdgeConstrained(mesh, curTet, 2 , 3)>>8),
-                       // there are 2 valid order for nodes: 1,0,2,3 and 0,2,1,3
-                       curNode[1], curNode[0], curNode[2], curNeigh[3]);
-      }
-      else{
-        HXT_CHECK( deletedPush(mesh, local, neigh) );
-      }
-    }
-  }
-
-  return HXT_STATUS_OK;
-}
-
-
-/**************************************************************
- * compute adjacencies with a matrix O(1) insertion and search
- **************************************************************/
-#ifndef HXT_DELAUNAY_LOW_MEMORY
-static inline HXTStatus computeAdjacenciesFast(HXTMesh* mesh, TetLocal* local, uint32_t* __restrict__ verticesID, const uint64_t blength){
-  cavityBnd_t* __restrict__ bnd = local->ball.bnd;
-
-#ifndef NDEBUG
-  int ghost_is_there = 0;
-#endif
-
-HXT_ASSERT(((size_t) bnd)%SIMD_ALIGN==0);
-HXT_ASSERT(((size_t) verticesID)%SIMD_ALIGN==0);
-
-#if !defined(HAVE_NO_OPENMP_SIMD)
-  #pragma omp simd aligned(verticesID,bnd:SIMD_ALIGN)
-#endif
-  for (uint32_t i=0; i<blength; i++){
-    verticesID[bnd[i].node[0]] = UINT32_MAX;
-    verticesID[bnd[i].node[1]] = UINT32_MAX;
-    if(bnd[i].node[2]!=HXT_GHOST_VERTEX){
-      verticesID[bnd[i].node[2]] = UINT32_MAX;
-    }
-  }
-
-  uint32_t npts = 1;
-  for (uint32_t i=0; i<blength; i++)
-  {
-    if(verticesID[bnd[i].node[0]]>npts){
-      verticesID[bnd[i].node[0]] = npts++;
-    }
-    bnd[i].node[0] = verticesID[bnd[i].node[0]];
-    if(verticesID[bnd[i].node[1]]>npts){
-      verticesID[bnd[i].node[1]] = npts++;
-    }
-    bnd[i].node[1] = verticesID[bnd[i].node[1]];
-
-    if(bnd[i].node[2]==HXT_GHOST_VERTEX){
-      bnd[i].node[2] = 0;
-#ifndef NDEBUG
-      ghost_is_there = 1;
-#endif
-    }
-    else{
-      if(verticesID[bnd[i].node[2]]>npts){
-        verticesID[bnd[i].node[2]] = npts++;
-      }
-      bnd[i].node[2] = verticesID[bnd[i].node[2]];
-    }
-
-  }
-
-  HXT_ASSERT_MSG((npts-3+ghost_is_there)*2==blength, "Failed to compute adjacencies (f) %u (%u ghost) vertices and %u cavity boundaries", npts-1+ghost_is_there, ghost_is_there, blength); // symbol undefined
-
-#if !defined(HAVE_NO_OPENMP_SIMD)
-  #pragma omp simd aligned(verticesID:SIMD_ALIGN)
-#endif
-  for (uint32_t i=0; i<blength; i++)
-  {
-    local->Map[bnd[i].node[0]*32 + bnd[i].node[1]] = bnd[i].neigh + 3;
-    local->Map[bnd[i].node[1]*32 + bnd[i].node[2]] = bnd[i].neigh + 1;
-    local->Map[bnd[i].node[2]*32 + bnd[i].node[0]] = bnd[i].neigh + 2;
-  }
-
-#if !defined(HAVE_NO_OPENMP_SIMD)
-  #pragma omp simd aligned(verticesID:SIMD_ALIGN)
-#endif
-  for (uint32_t i=0; i<blength; i++)
-  {
-    mesh->tetrahedra.neigh[bnd[i].neigh + 1] = local->Map[bnd[i].node[2]*32 + bnd[i].node[1]];
-    mesh->tetrahedra.neigh[bnd[i].neigh + 2] = local->Map[bnd[i].node[0]*32 + bnd[i].node[2]];
-    mesh->tetrahedra.neigh[bnd[i].neigh + 3] = local->Map[bnd[i].node[1]*32 + bnd[i].node[0]];
-  }
-
-  return HXT_STATUS_OK;
-}
-#endif
-
-
-/**************************************************************
- * compute adjacencies with a matrix O(n) insertion and search
- **************************************************************/
-static inline HXTStatus computeAdjacenciesSlow(HXTMesh* mesh, TetLocal* local, const uint64_t start, const uint64_t blength){
-
-  uint64_t tlength = 0;
-  const uint64_t middle = blength*3/2; // 3N
-
-  // N+2 point on the surface of the cavity
-  // 2N triangle on the surface of the cavity, x3 (4*0.5+1) data = 6N+9 uint64_t
-  // => enough place for the 3N edge x2 data = 6N uint64_t
-  uint64_t* Tmp = (uint64_t*) local->ball.bnd;
-  const unsigned index[4] = {2,3,1,2};
-
-  for (uint64_t i=0; i<blength; i++)
-  {
-    uint64_t curTet = local->deleted.tetID[start+ i];
-    const uint32_t* __restrict__ Node = mesh->tetrahedra.node + 4*curTet;
-
-    // pointer to the position of Node[0] in the Tmp array
-    for (unsigned j=0; j<3; j++)
-    {
-      // define the edge by the minimum vertex and the other
-      uint64_t key = ((uint64_t) Node[index[j]]<<32) + Node[index[j+1]];
-
-      // linear searching/pushing into Tmp
-      uint64_t k;
-      for (k=0; k<tlength; k++) // this is the only nested loop... the one that cost it all
-      {
-        __assume_aligned(Tmp, SIMD_ALIGN);
-        if(Tmp[k]==key)
-          break;
-      }
-
-      uint64_t curFace = 4*curTet+j+1;
-
-      // we did not found it
-      if(k==tlength){
-        Tmp[tlength] = (key>>32) + (key<<32);
-        Tmp[middle + tlength] = curFace;
-        tlength++;
-      }
-      else{// we found the neighbour !
-        uint64_t pairValue = Tmp[middle+k];
-        mesh->tetrahedra.neigh[curFace] = pairValue;
-        mesh->tetrahedra.neigh[pairValue] = curFace;
-        tlength--;
-        if(k<tlength){// put the last entry in the one we just discovered
-          Tmp[k] = Tmp[tlength];
-          Tmp[middle+k] = Tmp[middle + tlength];
-        }
-      }
-    }
-  }
-  HXT_ASSERT_MSG(tlength==0, "Failed to compute adjacencies (s)"); // verify that all neighbor were found
-  return HXT_STATUS_OK;
-}
-
-
-/****************************************
- * filling back the cavity (DelaunayBall)
- ****************************************/
-static inline HXTStatus fillingACavity(HXTMesh* mesh, TetLocal* local, uint32_t* __restrict__ verticesID, uint64_t* __restrict__ curTet, const uint32_t vta, const uint16_t color){
-  uint64_t clength = local->deleted.num;
-  uint64_t blength = local->ball.num;
-
-  uint64_t start = clength - blength;
-
-  // #pragma vector aligned
-#if !defined(HAVE_NO_OPENMP_SIMD)
-  #pragma omp simd
-#endif
-  for (uint64_t i=0; i<blength; i++)
-  {
-
-    __assume_aligned(local->deleted.tetID, SIMD_ALIGN);
-    __assume_aligned(local->ball.bnd, SIMD_ALIGN);
-    __assume_aligned(mesh->tetrahedra.colors, SIMD_ALIGN);
-    __assume_aligned(mesh->tetrahedra.flag, SIMD_ALIGN);
-    __assume_aligned(mesh->tetrahedra.node, SIMD_ALIGN);
-    __assume_aligned(mesh->tetrahedra.neigh, SIMD_ALIGN);
-
-    const uint64_t newTet = local->deleted.tetID[i + start];
-    uint32_t* __restrict__ Node = mesh->tetrahedra.node + 4*newTet;
-    mesh->tetrahedra.colors[newTet] = color;
-    mesh->tetrahedra.flag[newTet] = 0;
-
-    /* we need to always put the ghost vertex at the fourth slot*/
-    Node[0] = vta;
-    Node[1] = local->ball.bnd[i].node[0];
-    Node[2] = local->ball.bnd[i].node[1];
-    Node[3] = local->ball.bnd[i].node[2];
-
-    const uint64_t neigh = local->ball.bnd[i].neigh;
-    mesh->tetrahedra.neigh[4*newTet] = neigh;
-
-    mesh->tetrahedra.flag[newTet] = local->ball.bnd[i].flag;
-
-    // update neighbor's neighbor
-    mesh->tetrahedra.neigh[neigh] = 4*newTet;
-
-    // we recycle neigh to contain newTet (used in computeAdjacencies)
-    local->ball.bnd[i].neigh = 4*newTet;
-  }
-#ifndef HXT_DELAUNAY_LOW_MEMORY
-  if(blength<=58){ // N+2<=31 => N<=29 => 2N<=58
-  #ifndef NDEBUG
-    HXT_CHECK( computeAdjacenciesFast(mesh, local, verticesID, blength) );
-  #else
-    computeAdjacenciesFast(mesh, local, verticesID, blength);
-  #endif
-  }
-  else
-#endif
-  {
-  #ifndef NDEBUG
-    HXT_CHECK(computeAdjacenciesSlow(mesh, local, start, blength) );
-  #else
-    computeAdjacenciesSlow(mesh, local, start, blength);
-  #endif
-  }
-
-
-
-  *curTet = local->deleted.tetID[start];
-  local->deleted.num = start;
-
-  return HXT_STATUS_OK;
-}
-
-
-/*************************************************************
- * insert a single point
- ************************************************************/
-static inline HXTStatus insertion(HXTMesh* mesh,
-                                  uint32_t* verticesID,
-                                  TetLocal* local,
-                                  const double* nodalSizes,
-                                  uint64_t* curTet,
-                                  const uint32_t vta,
-                                  int perfectlyDelaunay){
-  const uint64_t prevDeleted = local->deleted.num;
-
-  HXT_CHECK( walking2Cavity(mesh, local, curTet, vta) );
-
-  if(nodalSizes!=NULL && filterTet(mesh, nodalSizes, *curTet, vta)){
-    return HXT_STATUS_FALSE;
-  }
-
-  const uint16_t color = mesh->tetrahedra.colors[*curTet];
-  int edgeConstraint = 0;
-  HXTStatus status = diggingACavity(mesh, local, *curTet, vta, &edgeConstraint);
-
-  if(status==HXT_STATUS_INTERNAL){
-    restoreDeleted(mesh, local, prevDeleted, color);
-    return HXT_STATUS_TRYAGAIN;
-  }
-  else{
-    HXT_CHECK(status);
-  }
-
-  if(edgeConstraint) {
-    HXT_CHECK( respectEdgeConstraint(local, mesh, vta, color, prevDeleted) );
-  }
-
-  // uint64_t face = 0;
-  // if(!perfectlyDelaunay && isStarShaped(local, mesh, vta, &face)==HXT_STATUS_INTERNAL) {
-  //   restoreDeleted(mesh, local, prevDeleted, color);
-  //   return HXT_STATUS_FALSE;
-  // }
-
-  // reshape the cavity if it is not star shaped
-  if(!perfectlyDelaunay)
-    HXT_CHECK( reshapeCavityIfNeeded(local, mesh, vta, prevDeleted) );
-
-  if(nodalSizes!=NULL && filterCavity(local, mesh, nodalSizes, vta)) {
-    restoreDeleted(mesh, local, prevDeleted, color);
-    return HXT_STATUS_FALSE;
-  }
-
-
-  if(local->ball.num > local->deleted.num){
-    uint64_t needed = MAX(DELETED_BUFFER_SIZE,local->ball.num)-local->deleted.num;
-
-    uint64_t ntet;
-
-    #pragma omp atomic capture
-    { ntet = mesh->tetrahedra.num; mesh->tetrahedra.num+=needed;}
-
-    reserveNewTet(mesh);
-    reserveNewDeleted(local, needed);
-
-#if !defined(HAVE_NO_OPENMP_SIMD)
-    #pragma omp simd
-#endif
-    for (uint64_t i=0; i<needed; i++){
-      local->deleted.tetID[local->deleted.num+i] = ntet+i;
-      mesh->tetrahedra.flag[ntet+i] = 0;
-      markTetAsDeleted(mesh, ntet+i);
-    }
-
-    local->deleted.num+=needed;
-  }
-
-  HXT_CHECK( fillingACavity(mesh, local, verticesID, curTet, vta, color) );
-
-  return HXT_STATUS_TRUE;
-}
-
-
-/*************************************************************
- * Delaunay triangulation of a set of points
- ************************************************************/
-static HXTStatus parallelDelaunay3D(HXTMesh* mesh,
-                                    HXTDelaunayOptions* options,
-                                    hxtNodeInfo* nodeInfo,
-                                    const uint32_t nToInsert,
-                                    int noReordering)
-{
-  uint32_t totalNumSkipped = 0;
-  uint32_t seed = 1;
-
-  // third, divide indices in different passes
-  const int maxThreads = options->delaunayThreads;
-  const int perfectlyDelaunay = mesh->tetrahedra.num<=5;
-
-  uint32_t passes[12];
-  unsigned npasses = computePasses(passes, options->numVerticesInMesh, nToInsert);
-
-  // that ugly cast because people want an array of double into the mesh structure
-  HXTVertex* vertices = (HXTVertex*) mesh->vertices.coord;
-  
-
-  /******************************************************
-          shuffle (and optimize cache locality)
-  ******************************************************/
-  if(noReordering){
-    // shuffle nodeInfo
-    HXT_CHECK( hxtNodeInfoShuffle(nodeInfo, nToInsert) );
-  }
-  else {
-    HXT_INFO_COND(options->verbosity>1, "Reordering vertices from %u to %u", mesh->vertices.num - nToInsert, mesh->vertices.num);
-    HXTVertex* verticesToInsert = vertices + mesh->vertices.num - nToInsert;
-
-    if(options->nodalSizes==NULL){
-      // shuffle the vertices to insert, then sort each pass except the first according to the hilbert curve...
-      HXT_CHECK( hxtVerticesShuffle(verticesToInsert, nToInsert) );
-    }
-    else{
-      HXT_CHECK( hxtNodeInfoShuffle(nodeInfo, nToInsert) );
-    }
-
-    uint32_t nbits = hxtAdvancedHilbertBits(options->bbox, options->minSizeStart, options->minSizeEnd,
-                                            options->numVerticesInMesh,
-                                            options->numVerticesInMesh + nToInsert,
-                                            options->numVerticesInMesh + nToInsert/4,
-                                            nToInsert/2,
-                                            maxThreads);
-    
-    HXT_CHECK( hxtVerticesHilbertDist(options->bbox, verticesToInsert, nToInsert, &nbits, NULL) );
-
-    if(options->nodalSizes==NULL){
-      for (unsigned i=options->numVerticesInMesh < SMALLEST_ROUND; i<npasses; i++) {
-        HXT_CHECK( hxtVerticesSort(verticesToInsert+passes[i], passes[i+1]-passes[i], nbits) );
-      }
-    }
-    else{
-      #pragma omp parallel for
-      for (int i=0; i<nToInsert; i++) {
-        nodeInfo[i].hilbertDist = verticesToInsert[i].padding.hilbertDist;
-      }
-
-      for (unsigned i=options->numVerticesInMesh < SMALLEST_ROUND; i<npasses; i++) {
-        HXT_CHECK( hxtNodeInfoSort(nodeInfo+passes[i], passes[i+1]-passes[i], nbits) );
-      }
-
-      const uint32_t nodalMin = mesh->vertices.num - nToInsert;
-      double* sizesToInsert = options->nodalSizes + nodalMin;
-
-      size_t vertSize = nToInsert*sizeof(HXTVertex);
-      size_t sizeSize = nToInsert*sizeof(double);
-      HXTVertex* vertCopy;
-      double* sizeCopy;
-      HXT_CHECK( hxtAlignedMalloc(&vertCopy, vertSize) );
-      HXT_CHECK( hxtAlignedMalloc(&sizeCopy, sizeSize) );
-      
-      #pragma omp parallel for
-      for (uint32_t i=0; i<nToInsert; i++) {
-        vertCopy[i] = verticesToInsert[nodeInfo[i].node-nodalMin];
-        sizeCopy[i] = sizesToInsert[nodeInfo[i].node-nodalMin];
-        nodeInfo[i].node = nodalMin + i;
-      }
-
-      memcpy(verticesToInsert, vertCopy, vertSize);
-      memcpy(sizesToInsert, sizeCopy, sizeSize);
-
-      HXT_CHECK( hxtAlignedFree(&vertCopy) );
-      HXT_CHECK( hxtAlignedFree(&sizeCopy) );
-    }
-  }
-
-  /******************************************************
-        Initializations and allocations
-  ******************************************************/
-  if(mesh->tetrahedra.num<5){
-    HXT_INFO_COND(options->verbosity>0,
-                  "Initialization of tet. mesh");
-    HXT_CHECK( hxtTetrahedraInit(mesh, nodeInfo, nToInsert, options->verbosity) );
-    options->numVerticesInMesh = 4; // not counting the ghost vertex
-    passes[0] = 4;
-  }
-
-
-  uint32_t*  verticesID;
-#ifdef HXT_DELAUNAY_LOW_MEMORY
-  verticesID = NULL; // we do not need it
-#else
-  HXT_CHECK( hxtAlignedMalloc(&verticesID, mesh->vertices.num*sizeof(uint32_t)) );
-#endif
-
-  TetLocal* Locals;
-  HXT_CHECK( hxtMalloc(&Locals, maxThreads*sizeof(TetLocal)) );
-  // HXT_CHECK( hxtMalloc())
-
-  for (int i=0; i<maxThreads; i++)
-    localInit(&Locals[i]);
-
-
-  HXT_INFO_COND(options->verbosity>0,
-                "Delaunay of %10u vertices on %3d threads\t- mesh.nvert: %-10u",
-                passes[npasses] - passes[0], maxThreads, options->numVerticesInMesh);
-
-  for (uint32_t p=0; p<npasses; p++)
-  {
-
-    double percent = 200;
-    int nthreads = 1;
-    uint32_t tmp = (passes[p+1]-passes[p])/SMALLEST_ROUND;
-    while(tmp>0 && nthreads<maxThreads){
-      tmp = tmp/2;
-      nthreads*=2;
-    }
-    nthreads = MIN(nthreads, maxThreads);
-
-    // const uint32_t initialPassLength = passes[p+1] - passes[p];
-
-    for(uint32_t n=0; passes[p+1]-passes[p]; n++)
-    {
-      const uint32_t passStart = passes[p];
-      const uint32_t passEnd = passes[p+1];
-      const uint32_t passLength = passEnd - passStart;
-
-      /******************************************************
-                      choosing number of threads
-      ******************************************************/
-      if(percent<140/nthreads || passLength<SMALLEST_ROUND){
-        nthreads=1;
-      }
-      else if(percent<20){
-        nthreads=(nthreads+1)/2;
-      }
-      else if(passLength < nthreads*SMALLEST_ROUND)
-        nthreads=(nthreads+1)/2;
-
-
-      /******************************************************
-                      Sorting vertices
-      ******************************************************/
-      double hxtDeclareAligned bboxShift[4]={0.5,0.5,0.5,0};
-
-      if(percent<100 && nthreads>1)
-      {
-        bboxShift[0] = (double) hxtReproducibleLCG(&seed)/RAND_MAX;
-        bboxShift[1] = (double) hxtReproducibleLCG(&seed)/RAND_MAX;
-        bboxShift[2] = (double) hxtReproducibleLCG(&seed)/RAND_MAX;
-        bboxShift[3] = (double) hxtReproducibleLCG(&seed)/RAND_MAX; // this is not a bbox deformation, it's an index shift
-      }
-
-      uint32_t nbits = hxtAdvancedHilbertBits(options->bbox, options->minSizeStart, options->minSizeEnd,
-                                                             options->numVerticesInMesh - passStart,
-                                                             options->numVerticesInMesh - passStart + nToInsert,
-                                                             options->numVerticesInMesh,
-                                                             passLength,
-                                                             nthreads);
-      if(noReordering){
-        HXT_CHECK( hxtVerticesHilbertDist(options->bbox, vertices, mesh->vertices.num, &nbits, bboxShift) );
-      }
-      else{
-        // TODO: do not recompute hilber dist of the whole mesh on 1 thread
-        HXT_CHECK( hxtVerticesHilbertDist(options->bbox, vertices, mesh->vertices.num - nToInsert + passEnd, &nbits, bboxShift) );
-      }
-      
-
-      #pragma omp parallel for simd aligned(nodeInfo:SIMD_ALIGN)
-      for (uint32_t i=passStart; i<passEnd; i++) {
-        nodeInfo[i].hilbertDist = vertices[nodeInfo[i].node].padding.hilbertDist;
-      }
-
-      if(p!=0 || n!=0 || nthreads>1 || options->numVerticesInMesh >= SMALLEST_ROUND){
-        HXT_CHECK( hxtNodeInfoSort(nodeInfo + passStart, passLength, nbits) );
-      }
-
-      const uint32_t step = passLength/nthreads;
-
-      uint32_t indexShift = MIN(step-1,(uint32_t) bboxShift[3]*step);
-
-      int threadFinished = 0;
-
-      #pragma omp parallel num_threads(nthreads)
-      {
-      #ifdef _MSC_VER
-        #pragma omp single
-        nthreads = omp_get_num_threads();
-      #endif
-
-        uint64_t curTet = 0; // we always begin with the first tet. (index 0)
-        const int threadID = omp_get_thread_num();
-
-        uint32_t localStart;
-        uint32_t localN;
-        int foundTet = 0;
-
-        if(nthreads>1){
-          // if(threadID<nthreads){
-
-          /******************************************************
-                          Making partitions
-          ******************************************************/
-          localStart = step*threadID + indexShift;
-          uint64_t dist = nodeInfo[passStart + localStart].hilbertDist;
-          
-          uint32_t up = 1;
-          while(localStart+up<passLength && dist==nodeInfo[passStart + localStart + up].hilbertDist)
-            up++;
-
-          localStart = localStart+up==passLength?0:localStart+up;
-          if(localStart > 0)
-            Locals[threadID].partition.startDist = (nodeInfo[passStart + localStart].hilbertDist
-                                                  + nodeInfo[passStart + localStart - 1].hilbertDist + 1)/2;
-          else
-            Locals[threadID].partition.startDist = nodeInfo[passStart + passLength-1].hilbertDist + (nodeInfo[passStart + localStart].hilbertDist - nodeInfo[passStart + passLength - 1].hilbertDist)/2;
-          Locals[threadID].partition.first = localStart;
-          // }
-
-          #pragma omp barrier
-
-          // if(threadID<nthreads){
-          uint32_t localEnd = Locals[(threadID+1)%nthreads].partition.first;
-          localN = (localEnd + passLength - localStart)%passLength;
-
-          Locals[threadID].partition.endDist = Locals[(threadID+1)%nthreads].partition.startDist;
-
-          // printf("%d) first dist: %lu, last dist: %lu startDist: %lu endDist: %lu\n", threadID, nodeInfo[passStart + localStart].hilbertDist, nodeInfo[(passStart + localStart + localN-1)%passLength].hilbertDist, Locals[threadID].partition.startDist, Locals[threadID].partition.endDist);
-
-
-          /******************************************************
-                          find starting tetrahedron
-          ******************************************************/
-
-          for (uint64_t i=0; i<mesh->tetrahedra.num; i++)
-          {
-            curTet = i;
-            if(isTetDeleted(mesh, i)==0 &&
-               checkTetrahedron(vertices, &Locals[threadID], mesh->tetrahedra.node + curTet*4 )==HXT_STATUS_OK)
-            {
-              foundTet = 1;
-              break;
-            }
-          }
-
-          if(options->reproducible){
-            Locals[threadID].partition.startDist = 0;
-            Locals[threadID].partition.endDist = UINT64_MAX;
-
-            // walk in total liberty toward the first point
-            HXTStatus status = walking2Cavity(mesh, &Locals[threadID], &curTet, nodeInfo[passStart + (localStart+localN/2)%passLength].node);
-
-            if(status!=HXT_STATUS_OK && status!=HXT_STATUS_TRYAGAIN){
-              HXT_OMP_CHECK( status );
-            }
-
-            Locals[threadID].partition.startDist = nodeInfo[passStart + localStart].hilbertDist;
-            Locals[threadID].partition.endDist = nodeInfo[passStart + localEnd].hilbertDist;
-
-            if(checkTetrahedron(vertices, &Locals[threadID], mesh->tetrahedra.node + curTet*4 )!=HXT_STATUS_OK){
-              foundTet = 0;
-              // check the neighbors
-              for (unsigned i=0; i<4; i++) {
-                uint64_t tet = mesh->tetrahedra.neigh[4*curTet+i]/4;
-                if(checkTetrahedron(vertices, &Locals[threadID], mesh->tetrahedra.node + tet*4 )==HXT_STATUS_OK){
-                  foundTet = 1;
-                  curTet = tet;
-                  break;
-                }
-              }
-            }
-          }
-
-          // }
-
-          #pragma omp barrier
-        }
-        else
-          // if(threadID==0)
-        {
-
-          /******************************************************
-             single-thread partition and starting tetrahedron
-          ******************************************************/
-          localStart = 0;
-          localN = passLength;
-          Locals[0].partition.startDist = 0;
-          Locals[0].partition.endDist = UINT64_MAX;
-
-          for (uint64_t i=0; i<mesh->tetrahedra.num; i++)
-          { 
-            if(isTetDeleted(mesh, i)==0){
-              curTet = i;
-              foundTet = 1;
-              break;
-            }
-          }
-        }
-
-        if (foundTet == 0) {
-          HXT_INFO_COND(options->verbosity>1,
-                        "thread %d did not find any tetrahedron to begin with", threadID);
-        }
-
-        // filtering vertices on the Moore curve
-        if(options->nodalSizes!=NULL)
-        {
-          double* p1 = NULL;
-          double p1Size = 0;
-
-          for (uint32_t i=0; i<localN; i++)
-          {
-            uint32_t passIndex = (localStart+i)%passLength;
-            uint32_t lastNode = nodeInfo[passStart + passIndex].node;
-            if(nodeInfo[passStart + passIndex].status==HXT_STATUS_TRYAGAIN){
-              double* p2 = vertices[lastNode].coord;
-              double p2Size = options->nodalSizes[lastNode];
-              if(p1!=NULL && pointIsTooClose(p1, p2, 0.5*(p1Size+p2Size))!=HXT_STATUS_OK){
-                nodeInfo[passStart + passIndex].status=HXT_STATUS_FALSE;
-              }
-              else{
-                p1 = p2;
-                p1Size = p2Size;
-              }
-            }
-          }
-        }
-
-
-        // if(threadID<nthreads){
-        if(foundTet!=0){
-
-          /******************************************************
-                          vertices insertion
-          ******************************************************/
-          for (uint32_t i=0; i<localN; i++)
-          {
-            uint32_t passIndex = (localStart+i)%passLength;
-            uint32_t vta = nodeInfo[passStart + passIndex].node;
-            if(nodeInfo[passStart + passIndex].status==HXT_STATUS_TRYAGAIN){
-              HXTStatus status = insertion(mesh, verticesID, &Locals[threadID], options->nodalSizes, &curTet, vta, perfectlyDelaunay);
-
-              switch(status){
-                case HXT_STATUS_TRYAGAIN:
-                  // ;
-                  if(nthreads==1){
-                    double* vtaCoord = vertices[vta].coord;
-                    HXT_WARNING("skipping supposedly duplicate vertex (%f %f %f)", vtaCoord[0], vtaCoord[1], vtaCoord[2]);
-                    nodeInfo[passStart + passIndex].status = HXT_STATUS_FALSE;
-                    break;
-                  }
-                case HXT_STATUS_FALSE:
-                case HXT_STATUS_TRUE:
-                  nodeInfo[passStart + passIndex].status = status;
-                  break;
-                default: // error other than HXT_STATUS_TRYAGAIN cause the program to return
-                  nodeInfo[passStart + passIndex].status = HXT_STATUS_TRYAGAIN;
-                  HXT_OMP_CHECK( status );
-                  break;
-              }
-            }
-            else{
-              nodeInfo[passStart + passIndex].status = HXT_STATUS_FALSE;
-            }
-          }  
-        }
-        // }
-
-        #pragma omp atomic update
-        threadFinished++;
-
-        int val = 0;
-        do{
-          // threads are waiting here for a reallocation
-          HXT_OMP_CHECK( synchronizeReallocation(mesh, &threadFinished, &val) );
-        }while(val<nthreads);
-        // }while(val<maxThreads);
-      }
-
-      /******************************************************
-      vertices that have to be tried again are put at the end
-      ******************************************************/
-      // everything above i+shift is HXT_STATUS_TRYAGAIN
-      uint32_t shift = 0;
-      unsigned numSkipped = 0;
-      for (uint32_t i=passEnd; i>passStart;)
-      {
-        i--;
-        if(nodeInfo[i].status!=HXT_STATUS_TRYAGAIN){
-          if(nodeInfo[i].status==HXT_STATUS_FALSE)
-            numSkipped++;
-          shift++;
-        }
-        else if(shift!=0) {
-          hxtNodeInfo tmp = nodeInfo[i];
-          nodeInfo[i] = nodeInfo[i+shift];
-          nodeInfo[i+shift] = tmp;
-        }
-      }
-
-      options->numVerticesInMesh += shift - numSkipped;
-
-      percent = (shift-numSkipped)*100.0/MAX(1,passLength-numSkipped);
-      totalNumSkipped += numSkipped;
-
-      HXT_INFO_COND(options->verbosity>1,
-                    "%3d thrd |%10u/%-10u-> %*.1f%-*c\t- mesh.nvert: %-10u",
-                    nthreads, shift-numSkipped, passLength-numSkipped, MIN(8,n/2)+5, percent, 8-MIN(8,n/2),'%', options->numVerticesInMesh);
-      
-      passes[p] += shift;
-    }
-  }
-
-  /******************************************************
-                  Cleaning
-  ******************************************************/
-  #pragma omp parallel num_threads(maxThreads)
-  {
-    const int threadID = omp_get_thread_num();
-    for (uint64_t i=0; i<Locals[threadID].deleted.num; i++) {
-      for (int j=0; j<4; j++) {
-        mesh->tetrahedra.neigh[4*Locals[threadID].deleted.tetID[i]+j] = HXT_NO_ADJACENT;
-      }
-    }
-  }
-  HXT_CHECK( hxtRemoveDeleted(mesh) );
-
-  for (int i=0; i<maxThreads; i++){
-    HXT_CHECK( hxtAlignedFree(&Locals[i].deleted.tetID) );
-    HXT_CHECK( hxtAlignedFree(&Locals[i].ball.bnd) );
-  }
-
-  HXT_CHECK( hxtAlignedFree(&verticesID) );
-  HXT_CHECK( hxtFree(&Locals) );
-
-  /***************************************************************
-    if reordering allowed, remove vertices we could not insert
-  ***************************************************************/
-  if(!noReordering && totalNumSkipped!=0){
-    /* remove deleted vertices and change tetrahedra.node accordingly */
-
-    uint32_t* numInserted;
-    HXT_CHECK( hxtAlignedMalloc(&numInserted, omp_get_max_threads()*sizeof(uint32_t)) );
-
-    uint32_t firstShifted = mesh->vertices.num - nToInsert;
-    uint32_t n = nToInsert;
-
-    // when a vertex was skipped, nodeInfo[i].status = HXT_STATUS_FALSE
-    #pragma omp parallel
-    {
-      // 1st: mark vertices with their corresponding status
-      #pragma omp for schedule(static)
-      for (uint32_t i=0; i<nToInsert; i++) {
-        uint32_t index = nodeInfo[i].node;
-        HXTStatus status = nodeInfo[i].status;
-        vertices[index].padding.status = status;
-      }// implicit barrier here
-
-      #pragma omp single
-      {
-        uint32_t i = 0;
-        while (vertices[firstShifted+i].padding.status==HXT_STATUS_TRUE) i++;
-
-        firstShifted += i+1;
-        n -= i+1;
-      }// implicit barrier here
-
-      uint32_t start = 0;
-      int threadID = omp_get_thread_num();
-      numInserted[threadID] = 0;
-
-      #pragma omp for schedule(static)
-      for (uint32_t i=0; i<n; i++) {
-        if(vertices[firstShifted+i].padding.status==HXT_STATUS_TRUE)
-          numInserted[threadID]++;
-      }// implicit barrier here
-
-      for (int i=0; i<threadID; i++) {
-        start+=numInserted[i];
-      }
-      start += firstShifted-1;
-
-      // 3rd: compute where each vertices will be
-      #pragma omp for schedule(static)
-      for (uint32_t i=0; i<n; i++) {
-        uint32_t oldStart = start;
-
-        if(vertices[firstShifted+i].padding.status==HXT_STATUS_TRUE)
-          start++;
-
-        // index and status are at the same location (it's a union) we cannot put this above the "if" !
-        vertices[firstShifted+i].padding.index = oldStart;
-      }
-
-      // 4th: update tetrahedra.node accordingly
-      #pragma omp for
-      for (uint64_t i=0; i<4*mesh->tetrahedra.num; i++) {
-        uint32_t index = mesh->tetrahedra.node[i];
-        if(index>=firstShifted && index!=HXT_GHOST_VERTEX)
-          mesh->tetrahedra.node[i] = vertices[index].padding.index;
-      }
-    }
-
-    HXT_CHECK( hxtAlignedFree(&numInserted) );
-
-    // 5th: put vertices at the right indices
-    for (uint32_t i=firstShifted; i<mesh->vertices.num; i++) {
-      if(options->nodalSizes!=NULL){
-        options->nodalSizes[vertices[i].padding.index] = options->nodalSizes[i];
-      }
-      vertices[vertices[i].padding.index] = vertices[i];
-    }
-
-    if(options->verbosity>1)
-      HXT_INFO("%u vertices removed (vertices not inserted in the mesh are removed when using hxtDelaunay)\n", totalNumSkipped);
-
-    mesh->vertices.num = mesh->vertices.num - totalNumSkipped;
-  }
-
-  HXT_INFO_COND(options->verbosity>0, "Delaunay done !%10u skipped", totalNumSkipped);
-  HXT_INFO_COND(options->verbosity>1, "mem. allocated:%5.2fGB - mesh.ntet: %-12lu - mesh.nvert: %-10lu",
-    ((50 + 2*(mesh->tetrahedra.flag!=NULL)) * mesh->tetrahedra.size +
-     (32 + 8*(options->nodalSizes!=NULL)) * mesh->vertices.size)/(1024.*1024.*1024.),
-    mesh->tetrahedra.num, mesh->vertices.num);
-
-  if(options->reproducible && maxThreads!=1){
-    HXT_INFO_COND(options->verbosity>1, "Reordering tetrahedra (reproducible==true)\n", mesh->vertices.num - nToInsert, mesh->vertices.num);
-    HXT_CHECK( hxtTetReorder(mesh) );
-  }
-
-  return HXT_STATUS_OK;
-}
-
-
-/*****************************************
- * complete the HXTDelaunayOptions struct
- * when there are missing fields.
- ****************************************/
-static HXTStatus DelaunayOptionsInit(HXTMesh* mesh,
-                                HXTDelaunayOptions* userOptions,
-                                HXTDelaunayOptions* options,
-                                HXTBbox* bbox){
-HXT_ASSERT(mesh!=NULL);
-
-  if(userOptions!=NULL){
-    options->bbox = userOptions->bbox;
-    options->nodalSizes = userOptions->nodalSizes;
-    options->verbosity = userOptions->verbosity;
-    options->minSizeStart = MAX(0.0, userOptions->minSizeStart);
-    options->minSizeEnd = MAX(options->minSizeStart, userOptions->minSizeEnd);
-    options->numVerticesInMesh = userOptions->numVerticesInMesh;
-    options->delaunayThreads = userOptions->delaunayThreads;
-    options->reproducible = userOptions->reproducible;
-  }
-  else{
-    HXTVertex* vertices = (HXTVertex*) mesh->vertices.coord;
-
-    // default parameters
-    options->bbox = NULL;
-    options->nodalSizes = NULL;
-    options->minSizeStart = 0.0;
-    options->minSizeEnd = 0.0;
-    options->verbosity = 1;
-    options->delaunayThreads = 0;
-    options->reproducible = 0;
-
-    // count the number of vertices in the mesh
-    #pragma omp parallel for
-    for (uint32_t i=0; i<mesh->vertices.num; i++) {
-      vertices[i].padding.index = 0;
-    }
-
-    #pragma omp parallel for
-    for (uint64_t i=0; i<mesh->tetrahedra.num; i++) {
-      vertices[mesh->tetrahedra.node[4*i+0]].padding.index = 1;
-      vertices[mesh->tetrahedra.node[4*i+1]].padding.index = 1;
-      vertices[mesh->tetrahedra.node[4*i+2]].padding.index = 1;
-      if(mesh->tetrahedra.node[4*i+3]!=HXT_GHOST_VERTEX)
-        vertices[mesh->tetrahedra.node[4*i+3]].padding.index = 1;
-    }
-
-    uint32_t numVerticesInMesh = 0;
-    #pragma omp parallel for reduction(+:numVerticesInMesh)
-    for (uint32_t i=0; i<mesh->vertices.num; i++) {
-        numVerticesInMesh += vertices[i].padding.index;
-    }
-
-    options->numVerticesInMesh = numVerticesInMesh;
-  }
-
-HXT_ASSERT(options->numVerticesInMesh <= mesh->vertices.num);
-
-  if(options->bbox==NULL){
-    options->bbox = bbox;
-    hxtBboxInit(bbox);
-    HXT_CHECK( hxtBboxAdd(bbox, mesh->vertices.coord, mesh->vertices.num) );
-  }
-
-  if(options->delaunayThreads==0)
-    options->delaunayThreads = omp_get_max_threads();
-  else if(options->delaunayThreads<0)
-    options->delaunayThreads = omp_get_num_procs();
-  
-  if(options->delaunayThreads>omp_get_thread_limit())
-    options->delaunayThreads = omp_get_thread_limit();
-
-  // for the predicates to work
-  exactinit(options->bbox->max[0]-options->bbox->min[0],
-            options->bbox->max[1]-options->bbox->min[1],
-            options->bbox->max[2]-options->bbox->min[2]);
-
-  return HXT_STATUS_OK;
-}
-
-
-/*****************************************
- * parallel Delaunay
- * see header for a complete description
- ****************************************/
-HXTStatus hxtDelaunay(HXTMesh* mesh, HXTDelaunayOptions* userOptions){
-  HXTDelaunayOptions options;
-  HXTBbox bbox;
-  HXT_CHECK( DelaunayOptionsInit(mesh, userOptions, &options, &bbox) );
-
-  const uint32_t nToInsert = mesh->vertices.num - options.numVerticesInMesh;
-
-  if(options.reproducible && nToInsert<2048) // not worth launching threads and having to reorder tets after...
-    options.delaunayThreads = 1;
-
-  hxtNodeInfo* nodeInfo;
-  HXT_CHECK( hxtAlignedMalloc(&nodeInfo, nToInsert*sizeof(hxtNodeInfo)) );
-  
-  // we fill nodeInfo with the indices of each vertices to insert...
-  #pragma omp parallel for simd
-  for (uint32_t i=0; i<nToInsert; i++) {
-    nodeInfo[i].node = options.numVerticesInMesh + i;
-    nodeInfo[i].status = HXT_STATUS_TRYAGAIN; // necessary for when foundTet = 0;
-  }
-
-  HXT_CHECK( parallelDelaunay3D(mesh, &options, nodeInfo, nToInsert, 0) );
-
-  HXT_CHECK( hxtAlignedFree(&nodeInfo) );
-
-  return HXT_STATUS_OK;
-}
-
-
-/************************************************
- * parallel Delaunay without moving the vertices
- * see header for a complete description
- ***********************************************/
-HXTStatus hxtDelaunaySteadyVertices(HXTMesh* mesh, HXTDelaunayOptions* userOptions, hxtNodeInfo* nodeInfo, uint64_t nToInsert){
-HXT_ASSERT(nodeInfo!=NULL);
-
-  HXTDelaunayOptions options;
-  HXTBbox bbox;
-  HXT_CHECK( DelaunayOptionsInit(mesh, userOptions, &options, &bbox) );
-
-  if(options.reproducible && nToInsert<2048) // not worth launching threads and having to reorder tets after...
-    options.delaunayThreads = 1;
-
-HXT_ASSERT(options.numVerticesInMesh+nToInsert <= mesh->vertices.num);
-
-  HXT_CHECK( parallelDelaunay3D(mesh, &options, nodeInfo, nToInsert, 1) );
-
-  return HXT_STATUS_OK;
-}
-
diff --git a/contrib/hxt/hxt_tetrahedra.h b/contrib/hxt/hxt_tetrahedra.h
deleted file mode 100644
index 5511dd5b93..0000000000
--- a/contrib/hxt/hxt_tetrahedra.h
+++ /dev/null
@@ -1,113 +0,0 @@
-#ifndef _HXT_TETRAHEDRA_
-#define _HXT_TETRAHEDRA_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "hxt_mesh.h"
-#include "hxt_vertices.h"
-
-/**
-* \file tetrahedra.h Delaunay tetrahedrization
-* \author Célestin Marot
-*/
-
-/**
- * \struct HXTDelaunayOptions
- * 
- * Options for the Delaunay functions hxtDelaunay() and hxtDelaunaySteadyVertices()
- * 
- *
- */
-typedef struct {
-  HXTBbox* bbox;              /**< The bounding box for all vertices.
-                               *  - if bbox==NULL, the bbox is recomputed internally;
-                               *  - if bbox!=NULL, bbox must contain all vertices */
-
-  double* nodalSizes;         /**<
-                               *  - if nodalSize==NULL, doesn't restrict nodalSize;
-                               *  - if nodalSize!=NULL, nodalSize contains the minimum
-                               *  mesh size at each vertex.\n
-                               *  If the insertion of a vertex create an edge smaller than
-                               * the average nodalSize of its endpoints, the vertex is
-                               * not inserted
-                               *  \warning a segmentation fault will occur if a vertex
-                               * doesn't have a corresponding mesh size */
-
-  double minSizeStart;         /**< estimate of the minimum mesh size at the moment of the call. 
-                                * 0 if the mesh is empty or if the distribution is uniform
-                                * (the mesh size is then guessed with the number of point) */
-  double minSizeEnd;           /**< estimate of the minimum mesh size when all points are inserted in the Delaunay. 
-                                * 0 if the distribution is uniform
-                                * (the mesh size is then guessed with the number of point) */
-
-  uint32_t numVerticesInMesh; /**< The number of vertices in the mesh */
-
-  int verbosity;              /**<
-                               *  - if verbosity<=0: don't print information.
-                               *  - if verbosity==1: print basic information on each pass
-                               *  - if verbosity>=2: print everything */
-
-  int reproducible;           /**< If reproducible!=0, the Delaunay use a reproducible tetrahedra order
-                               * in order to be totally deterministic.
-                               * \warning this takes time !
-                               * It requires a total reordering of tetrahedra at the end to get a reproducible order\n
-                               * except if `delaunayThreads==1 || (delaunayThreads==0 && omp_get_max_threads()==1)`\n
-                               * in which case it is reproducible anyway */
-
-  int delaunayThreads;        /**< number of threads for the delaunay insertion
-                               *  - if delaunayThreads==0, it will use omp_get_max_threads()
-                               *  - if delaunayThreads<0, it will uses omp_get_num_procs() */
-} HXTDelaunayOptions;
-
-
-/**
- * \brief Delaunay of a set of vertices that does not modify their order
- * \details This perform the insertion of the vertices whose indices are
- * given in nodeInfo (in the \ref hxtNodeInfo.node wtructure member)\n
- * This function does not change the order of vertices in the mesh.\n
- * \ref hxtNodeInfo.status will be modified by the function to tell
- * if the vertex was successfully inserted or not.
- *  - nodeInfo[i].status==HXT_STATUS_TRUE  if the vertex was successfully inserted.
- *  - nodeInfo[i].status==HXT_STATUS_FALSE  if the vertex was not inserted.
- *  - nodeInfo[i].status==HXT_STATUS_TRYAGAIN  if an error occured before the vertex could be inserted
- *
- * \warning
- *  - the order of nodeInfo will change
- *  - hxtNodeInfo[i].hilbertDist will change
- *  - mesh->tetrahedra.* will change
- *  - mesh->vertices.coord[4*i+3] will change
- *
- * \param mesh: a valid Delaunay mesh
- * \param options: options to give to the Delaunay algorithm \ref HXTDelaunayOptions
- * \param[in, out] nodeInfo: the indices of the vertices to insert in the tetrahedral mesh.
- * \param nToInset: the number of element in nodeInfo, hence the number of vertices to insert.
- */
-HXTStatus hxtDelaunaySteadyVertices(HXTMesh* mesh, HXTDelaunayOptions* options, hxtNodeInfo* nodeInfo, uint64_t nToInsert);
-
-
-/**
- * \brief Delaunay of a set of vertices
- * \details This perform the insertion of the vertices
- * from numVerticesInMesh to mesh->vertices.num\n
- *
- * \warning
- *  - the order of mesh->vertices will change
- *  - hxtNodeInfo[i].hilbertDist will change
- *  - mesh->tetrahedra.* will change
- *  - mesh->vertices.coord[4*i+3] will change
- *  - vertices that could not be inserted are deleted from mesh->vertices !
- *
- * \param mesh: a valid Delaunay mesh
- * \param options: options to give to the Delaunay algorithm \ref HXTDelaunayOptions
- */
-HXTStatus hxtDelaunay(HXTMesh* mesh, HXTDelaunayOptions* options);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
diff --git a/contrib/hxt/hxt_tools.c b/contrib/hxt/hxt_tools.c
deleted file mode 100644
index f12fbcae51..0000000000
--- a/contrib/hxt/hxt_tools.c
+++ /dev/null
@@ -1,138 +0,0 @@
-#include "hxt_api.h"
-#include "hxt_tools.h"
-
-HXTStatus hxtNorm2V(double v[3], int size, double* norm2){
-  *norm2=0.0;
-  for(int i=0; i<size; i++)
-    *norm2+=v[i]*v[i];
-  *norm2 = sqrt(*norm2);
-  return HXT_STATUS_OK;
-}
-
-HXTStatus hxtNorm2V3(double v[3], double* norm2){
-  *norm2 = sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
-  return HXT_STATUS_OK;
-}
-
-HXTStatus hxtNormalizeV(double *v, int size){
-  double norm=0.0;
-  hxtNorm2V(v,size,&norm);
-  for(int i=0; i<size; i++)
-    v[i] /= norm;
-  return HXT_STATUS_OK;
-}
-
-HXTStatus hxtNormalizeV3(double v[3]){
-  double norm=0.0;
-  hxtNorm2V3(v,&norm);
-  v[0] /= norm;
-  v[1] /= norm;
-  v[2] /= norm;
-  return HXT_STATUS_OK;
-}
-
-HXTStatus hxtCrossProductV3(double a[3], double b[3], double res[3]){
-  res[0] = a[1]*b[2] - a[2]*b[1];
-  res[1] = a[2]*b[0] - a[0]*b[2];
-  res[2] = a[0]*b[1] - a[1]*b[0];
-  return HXT_STATUS_OK;
-}
-
-HXTStatus hxtDet2x2(double mat[2][2], double* det){
-  *det = mat[0][0]*mat[1][1]-mat[0][1]*mat[1][0];
-  return HXT_STATUS_OK;
-}
-
-HXTStatus hxtInv2x2(double mat[2][2], double inv[2][2], double *det){
-  hxtDet2x2(mat,det);
-  if(*det) {
-    const double ud = 1. / *det;
-    inv[0][0] =  mat[1][1] * ud;
-    inv[0][1] = -mat[0][1] * ud;
-    inv[1][0] = -mat[1][0] * ud;
-    inv[1][1] =  mat[0][0] * ud;
-  } else {
-    return HXT_STATUS_ERROR;
-  }
-  return HXT_STATUS_OK;
-}
-
-HXTStatus hxtDet3x3(double mat[3][3], double *det)
-{
-  *det = (mat[0][0] * (mat[1][1] * mat[2][2] - mat[1][2] * mat[2][1]) -
-          mat[0][1] * (mat[1][0] * mat[2][2] - mat[1][2] * mat[2][0]) +
-          mat[0][2] * (mat[1][0] * mat[2][1] - mat[1][1] * mat[2][0]));
-  return HXT_STATUS_OK;
-}
-
-HXTStatus hxtInv3x3(double mat[3][3], double inv[3][3], double *det)
-{
-  HXT_CHECK(hxtDet3x3(mat, det));
-  if(*det){
-    double ud = 1. / *det;
-    inv[0][0] =  (mat[1][1] * mat[2][2] - mat[1][2] * mat[2][1]) * ud;
-    inv[1][0] = -(mat[1][0] * mat[2][2] - mat[1][2] * mat[2][0]) * ud;
-    inv[2][0] =  (mat[1][0] * mat[2][1] - mat[1][1] * mat[2][0]) * ud;
-    inv[0][1] = -(mat[0][1] * mat[2][2] - mat[0][2] * mat[2][1]) * ud;
-    inv[1][1] =  (mat[0][0] * mat[2][2] - mat[0][2] * mat[2][0]) * ud;
-    inv[2][1] = -(mat[0][0] * mat[2][1] - mat[0][1] * mat[2][0]) * ud;
-    inv[0][2] =  (mat[0][1] * mat[1][2] - mat[0][2] * mat[1][1]) * ud;
-    inv[1][2] = -(mat[0][0] * mat[1][2] - mat[0][2] * mat[1][0]) * ud;
-    inv[2][2] =  (mat[0][0] * mat[1][1] - mat[0][1] * mat[1][0]) * ud;
-    return HXT_STATUS_OK;
-  }
-  else{
-    for(int i = 0; i < 3; i++)
-      for(int j = 0; j < 3; j++)
-        inv[i][j] = 0.;
-    return HXT_ERROR_MSG(HXT_STATUS_FAILED, "Singular matrix 3x3");
-  }
-}
-
-HXTStatus hxtInv4x4ColumnMajor(double m[16], double invOut[16], double *det)
-{
-  double inv[16];
-  int i;
-  
-  inv[ 0] =  m[5] * m[10] * m[15] - m[5] * m[11] * m[14] - m[9] * m[6] * m[15] + m[9] * m[7] * m[14] + m[13] * m[6] * m[11] - m[13] * m[7] * m[10];
-  inv[ 4] = -m[4] * m[10] * m[15] + m[4] * m[11] * m[14] + m[8] * m[6] * m[15] - m[8] * m[7] * m[14] - m[12] * m[6] * m[11] + m[12] * m[7] * m[10];
-  inv[ 8] =  m[4] * m[ 9] * m[15] - m[4] * m[11] * m[13] - m[8] * m[5] * m[15] + m[8] * m[7] * m[13] + m[12] * m[5] * m[11] - m[12] * m[7] * m[ 9];
-  inv[12] = -m[4] * m[ 9] * m[14] + m[4] * m[10] * m[13] + m[8] * m[5] * m[14] - m[8] * m[6] * m[13] - m[12] * m[5] * m[10] + m[12] * m[6] * m[ 9];
-  inv[ 1] = -m[1] * m[10] * m[15] + m[1] * m[11] * m[14] + m[9] * m[2] * m[15] - m[9] * m[3] * m[14] - m[13] * m[2] * m[11] + m[13] * m[3] * m[10];
-  inv[ 5] =  m[0] * m[10] * m[15] - m[0] * m[11] * m[14] - m[8] * m[2] * m[15] + m[8] * m[3] * m[14] + m[12] * m[2] * m[11] - m[12] * m[3] * m[10];
-  inv[ 9] = -m[0] * m[ 9] * m[15] + m[0] * m[11] * m[13] + m[8] * m[1] * m[15] - m[8] * m[3] * m[13] - m[12] * m[1] * m[11] + m[12] * m[3] * m[ 9];
-  inv[13] =  m[0] * m[ 9] * m[14] - m[0] * m[10] * m[13] - m[8] * m[1] * m[14] + m[8] * m[2] * m[13] + m[12] * m[1] * m[10] - m[12] * m[2] * m[ 9];
-  inv[ 2] =  m[1] * m[ 6] * m[15] - m[1] * m[ 7] * m[14] - m[5] * m[2] * m[15] + m[5] * m[3] * m[14] + m[13] * m[2] * m[ 7] - m[13] * m[3] * m[ 6];
-  inv[ 6] = -m[0] * m[ 6] * m[15] + m[0] * m[ 7] * m[14] + m[4] * m[2] * m[15] - m[4] * m[3] * m[14] - m[12] * m[2] * m[ 7] + m[12] * m[3] * m[ 6];
-  inv[10] =  m[0] * m[ 5] * m[15] - m[0] * m[ 7] * m[13] - m[4] * m[1] * m[15] + m[4] * m[3] * m[13] + m[12] * m[1] * m[ 7] - m[12] * m[3] * m[ 5];
-  inv[14] = -m[0] * m[ 5] * m[14] + m[0] * m[ 6] * m[13] + m[4] * m[1] * m[14] - m[4] * m[2] * m[13] - m[12] * m[1] * m[ 6] + m[12] * m[2] * m[ 5];
-  inv[ 3] = -m[1] * m[ 6] * m[11] + m[1] * m[ 7] * m[10] + m[5] * m[2] * m[11] - m[5] * m[3] * m[10] - m[ 9] * m[2] * m[ 7] + m[ 9] * m[3] * m[ 6];
-  inv[ 7] =  m[0] * m[ 6] * m[11] - m[0] * m[ 7] * m[10] - m[4] * m[2] * m[11] + m[4] * m[3] * m[10] + m[ 8] * m[2] * m[ 7] - m[ 8] * m[3] * m[ 6];
-  inv[11] = -m[0] * m[ 5] * m[11] + m[0] * m[ 7] * m[ 9] + m[4] * m[1] * m[11] - m[4] * m[3] * m[ 9] - m[ 8] * m[1] * m[ 7] + m[ 8] * m[3] * m[ 5];
-  inv[15] =  m[0] * m[ 5] * m[10] - m[0] * m[ 6] * m[ 9] - m[4] * m[1] * m[10] + m[4] * m[2] * m[ 9] + m[ 8] * m[1] * m[ 6] - m[ 8] * m[2] * m[ 5];
-  
-  *det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12];
-  
-  if(*det == 0)
-    return HXT_STATUS_ERROR;
-    
-  double invDet = 1.0 / *det;
-  
-  for(i = 0; i < 16; i++)
-    invOut[i] = inv[i] * invDet;
-  
-  return HXT_STATUS_OK;
-}
-
-HXTStatus hxtJacobianLinTet(double *x , double *y, double *z , double mat[3][3]){
-  mat[0][0] = x[1] - x[0];
-  mat[0][1] = x[2] - x[0];
-  mat[0][2] = x[3] - x[0];
-  mat[1][0] = y[1] - y[0];
-  mat[1][1] = y[2] - y[0];
-  mat[1][2] = y[3] - y[0];
-  mat[2][0] = z[1] - z[0];
-  mat[2][1] = z[2] - z[0];
-  mat[2][2] = z[3] - z[0];  
-  return HXT_STATUS_OK;
-}
diff --git a/contrib/hxt/laplace_main.c b/contrib/hxt/laplace_main.c
deleted file mode 100644
index ad72100f42..0000000000
--- a/contrib/hxt/laplace_main.c
+++ /dev/null
@@ -1,16 +0,0 @@
-#include "hxt_api.h"
-#include "hxt_laplace.h"
-#include "hxt_linear_system.h"
-int main(int argc, char **argv) {
-  if (argc != 2)
-    return HXT_ERROR_MSG(HXT_STATUS_FAILED,"usage: laplace input.msh");
-  HXT_CHECK(hxtInitializeLinearSystems(&argc, &argv));
-
-  HXTContext *context;
-  hxtContextCreate(&context);
-  HXTMesh *mesh;
-  HXT_CHECK(hxtMeshCreate(context, &mesh));
-  HXT_CHECK(hxtMeshReadGmsh(mesh, argv[1]));
-  HXT_CHECK(hxtLaplace(mesh));  
-  return HXT_STATUS_OK;
-}
diff --git a/contrib/hxt/predicates.h b/contrib/hxt/predicates.h
deleted file mode 100644
index 35d171f1a5..0000000000
--- a/contrib/hxt/predicates.h
+++ /dev/null
@@ -1,72 +0,0 @@
-#ifndef _ROBUST_PREDICATES_H_
-#define _ROBUST_PREDICATES_H_
-
-#include <hxt_tools.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern double splitter;
-extern double o3dstaticfilter;
-extern double o3derrboundA;
-extern double ispstaticfilter;
-extern double isperrboundA;
-
-double exactinit(double maxx, double maxy, double maxz);
-// double incircle(double *pa, double *pb, double *pc, double *pd);
-
-/** \todo Please comment the freaking variable type you are using. [JP]
- */
-double insphere(
-  const double* const __restrict__ pa,
-  const double* const __restrict__ pb,
-  const double* const __restrict__ pc,
-  const double* const __restrict__ pd,
-  const double* const __restrict__ pe);
-
-double orient3d(
-  const double* const __restrict__ pa,
-  const double* const __restrict__ pb,
-  const double* const __restrict__ pc,
-  const double* const __restrict__ pd);
-
-double incircle(
-  const double* const __restrict__ pa,
-  const double* const __restrict__ pb,
-  const double* const __restrict__ pc,
-  const double* const __restrict__ pd);
-
-double orient2d(
-  const double* const __restrict__ pa,
-  const double* const __restrict__ pb,
-  const double* const __restrict__ pc);
-
-int grow_expansion(
-  int elen, const double *e, double b, double *h);
-
-int grow_expansion_zeroelim(
-  int elen, const double *e, double b, double *h);
-
-int fast_expansion_sum_zeroelim(
-  const int elen, const double *e,
-  const int flen, const double *f, double *h);
-
-int fast_expansion_sum(
-  int elen, const double *e, int flen, const double *f, double *h);
-
-int fast_expansion_sum_zeroelim(
-  const int elen, const double *e,
-  const int flen, const double *f, double *h);
-
-int scale_expansion(
-  const int elen, const double *e, const double b, double *h);
-
-int scale_expansion_zeroelim(
-  const int elen, const double *e, const double b, double *h);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/contrib/hxt/predicates/CMakeLists.txt b/contrib/hxt/predicates/CMakeLists.txt
new file mode 100644
index 0000000000..6b12f414f1
--- /dev/null
+++ b/contrib/hxt/predicates/CMakeLists.txt
@@ -0,0 +1,32 @@
+cmake_minimum_required(VERSION 3.9)
+project(hxt_predicates C)
+
+if(TARGET hxt_predicates)
+  # header guard for CMake. You need to include this directory first
+  return()
+endif()
+
+set(HXT_PREDICATES_SRC
+	"${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})
+
+target_include_directories(hxt_predicates INTERFACE include)
+
+# do not use extended double precision or arithmetic contraction in predicates.c
+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")
+elseif(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang")
+	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.")
+endif()
diff --git a/contrib/hxt/predicates/include/predicates.h b/contrib/hxt/predicates/include/predicates.h
new file mode 100644
index 0000000000..b52dffb39b
--- /dev/null
+++ b/contrib/hxt/predicates/include/predicates.h
@@ -0,0 +1,98 @@
+#ifndef ROBUST_PREDICATES_H
+#define ROBUST_PREDICATES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern double splitter;
+extern double o3dstaticfilter;
+extern double o3derrboundA;
+extern double ispstaticfilter;
+extern double isperrboundA;
+
+void exactinit(double maxx, double maxy, double maxz);
+
+double insphere(
+  const double* const __restrict__ pa,
+  const double* const __restrict__ pb,
+  const double* const __restrict__ pc,
+  const double* const __restrict__ pd,
+  const double* const __restrict__ pe);
+
+double orient3d(
+  const double* const __restrict__ pa,
+  const double* const __restrict__ pb,
+  const double* const __restrict__ pc,
+  const double* const __restrict__ pd);
+
+double incircle(
+  const double* const __restrict__ pa,
+  const double* const __restrict__ pb,
+  const double* const __restrict__ pc,
+  const double* const __restrict__ pd);
+
+double orient2d(
+  const double* const __restrict__ pa,
+  const double* const __restrict__ pb,
+  const double* const __restrict__ pc);
+
+
+/* if you want a rough idea of the volume of one tet, but you don't need
+ * exact sign computation */
+static inline double orient3d_inexact(const double* __restrict__  pa,
+                                      const double* __restrict__  pb,
+                                      const double* __restrict__  pc,
+                                      const double* __restrict__  pd)
+{
+  double adx, bdx, cdx, ady, bdy, cdy, adz, bdz, cdz;
+  double bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
+
+  adx = pa[0] - pd[0];
+  bdx = pb[0] - pd[0];
+  cdx = pc[0] - pd[0];
+  ady = pa[1] - pd[1];
+  bdy = pb[1] - pd[1];
+  cdy = pc[1] - pd[1];
+  adz = pa[2] - pd[2];
+  bdz = pb[2] - pd[2];
+  cdz = pc[2] - pd[2];
+
+  bdxcdy = bdx * cdy;
+  cdxbdy = cdx * bdy;
+
+  cdxady = cdx * ady;
+  adxcdy = adx * cdy;
+
+  adxbdy = adx * bdy;
+  bdxady = bdx * ady;
+
+  return adz * (bdxcdy - cdxbdy)
+       + bdz * (cdxady - adxcdy)
+       + cdz * (adxbdy - bdxady);
+}
+
+
+// remember to call exactinit with the right ranges beforehand !!!
+static inline int orient3d_inline(const double* __restrict__  pa,
+                                  const double* __restrict__  pb,
+                                  const double* __restrict__  pc,
+                                  const double* __restrict__  pd)
+{
+  double det = orient3d_inexact(pa, pb, pc, pd);
+
+  int ret = (det > o3dstaticfilter) - (det < -o3dstaticfilter);
+
+  if (ret!=0) return ret;
+
+  det = orient3d(pa,pb,pc,pd);
+
+  return (det>0.0) - (det<0.0);
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/contrib/hxt/predicates.c b/contrib/hxt/predicates/src/predicates.c
similarity index 89%
rename from contrib/hxt/predicates.c
rename to contrib/hxt/predicates/src/predicates.c
index c9b7b54058..315a44211b 100644
--- a/contrib/hxt/predicates.c
+++ b/contrib/hxt/predicates/src/predicates.c
@@ -123,15 +123,6 @@
 #include <fpu_control.h>
 #endif /* LINUX */
 
-#include "hxt_tools.h"
-
-#ifdef _MSC_VER
-#pragma fp_contract (off) // disable floating-point contraction
-                          // same as -ffp-contract=off in gcc
-                          // done by -fp-model strict in icc
-#endif
-
-
 /* On some machines, the exact arithmetic routines might be defeated by the  */
 /*   use of internal extended precision floating-point registers.  Sometimes */
 /*   this problem can be fixed by defining certain values to be volatile,    */
@@ -180,10 +171,6 @@
   x = (REAL) (a + b); \
   Fast_Two_Sum_Tail(a, b, x, y)
 
-#define Fast_Two_Diff_Tail(a, b, x, y) \
-  bvirt = a - x; \
-  y = bvirt - b
-
 #define Two_Sum_Tail(a, b, x, y) \
   bvirt = (REAL) (x - a); \
   avirt = x - bvirt; \
@@ -235,16 +222,6 @@
   err3 = err2 - (ahi * blo); \
   y = (alo * blo) - err3
 
-/* Two_Product_2Presplit() is Two_Product() where both of the inputs have    */
-/*   already been split.  Avoids redundant splitting.                        */
-
-#define Two_Product_2Presplit(a, ahi, alo, b, bhi, blo, x, y) \
-  x = (REAL) (a * b); \
-  err1 = x - (ahi * bhi); \
-  err2 = err1 - (alo * bhi); \
-  err3 = err2 - (ahi * blo); \
-  y = (alo * blo) - err3
-
 /* Square() can be done more quickly than Two_Product().                     */
 
 #define Square_Tail(a, x, y) \
@@ -276,10 +253,6 @@
   Two_One_Diff(a1, a0, b0, _j, _0, x0); \
   Two_One_Diff(_j, _0, b1, x3, x2, x1)
 
-#define Four_One_Sum(a3, a2, a1, a0, b, x4, x3, x2, x1, x0) \
-  Two_One_Sum(a1, a0, b , _j, x1, x0); \
-  Two_One_Sum(a3, a2, _j, x4, x3, x2)
-
 #define Two_One_Product(a1, a0, b, x3, x2, x1, x0) \
   Split(b, bhi, blo); \
   Two_Product_Presplit(a0, b, bhi, blo, _i, x0); \
@@ -288,44 +261,6 @@
   Fast_Two_Sum(_j, _k, x3, x2)
 
 
-#define Two_Two_Product(a1, a0, b1, b0, x7, x6, x5, x4, x3, x2, x1, x0) \
-  Split(a0, a0hi, a0lo); \
-  Split(b0, bhi, blo); \
-  Two_Product_2Presplit(a0, a0hi, a0lo, b0, bhi, blo, _i, x0); \
-  Split(a1, a1hi, a1lo); \
-  Two_Product_2Presplit(a1, a1hi, a1lo, b0, bhi, blo, _j, _0); \
-  Two_Sum(_i, _0, _k, _1); \
-  Fast_Two_Sum(_j, _k, _l, _2); \
-  Split(b1, bhi, blo); \
-  Two_Product_2Presplit(a0, a0hi, a0lo, b1, bhi, blo, _i, _0); \
-  Two_Sum(_1, _0, _k, x1); \
-  Two_Sum(_2, _k, _j, _1); \
-  Two_Sum(_l, _j, _m, _2); \
-  Two_Product_2Presplit(a1, a1hi, a1lo, b1, bhi, blo, _j, _0); \
-  Two_Sum(_i, _0, _n, _0); \
-  Two_Sum(_1, _0, _i, x2); \
-  Two_Sum(_2, _i, _k, _1); \
-  Two_Sum(_m, _k, _l, _2); \
-  Two_Sum(_j, _n, _k, _0); \
-  Two_Sum(_1, _0, _j, x3); \
-  Two_Sum(_2, _j, _i, _1); \
-  Two_Sum(_l, _i, _m, _2); \
-  Two_Sum(_1, _k, _i, x4); \
-  Two_Sum(_2, _i, _k, x5); \
-  Two_Sum(_m, _k, x7, x6)
-
-/* An expansion of length two can be squared more quickly than finding the   */
-/*   product of two different expansions of length two, and the result is    */
-/*   guaranteed to have no more than six (rather than eight) components.     */
-
-#define Two_Square(a1, a0, x5, x4, x3, x2, x1, x0) \
-  Square(a0, _j, x0); \
-  _0 = a0 + a0; \
-  Two_Product(a1, _0, _k, _1); \
-  Two_One_Sum(_k, _1, _j, _l, _2, x1); \
-  Square(a1, _j, _1); \
-  Two_Two_Sum(_j, _1, _l, _2, x5, x4, x3, x2)
-
 /* splitter = 2^ceiling(p / 2) + 1.  Used to split floats in half.           */
 REAL splitter;
 static REAL epsilon;         /* = 2^(-p).  Used to estimate roundoff errors. */
@@ -447,156 +382,6 @@ void exactinit(REAL maxx, REAL maxy, REAL maxz)
   ispstaticfilter = 1.2466136531027298e-13 * maxx * maxy * maxz * (maxz * maxz);
 }
 
-/*****************************************************************************/
-/*                                                                           */
-/*  grow_expansion()   Add a scalar to an expansion.                         */
-/*                                                                           */
-/*  Sets h = e + b.  See the long version of my paper for details.           */
-/*                                                                           */
-/*  Maintains the nonoverlapping property.  If round-to-even is used (as     */
-/*  with IEEE 754), maintains the strongly nonoverlapping and nonadjacent    */
-/*  properties as well.  (That is, if e has one of these properties, so      */
-/*  will h.)                                                                 */
-/*                                                                           */
-/*****************************************************************************/
-
-int grow_expansion(int elen, const REAL *e, REAL b, REAL *h)
-/* e and h can be the same. */
-{
-  REAL Q;
-  INEXACT REAL Qnew;
-  int eindex;
-  REAL enow;
-  INEXACT REAL bvirt;
-  REAL avirt, bround, around;
-
-  Q = b;
-  for (eindex = 0; eindex < elen; eindex++) {
-    enow = e[eindex];
-    Two_Sum(Q, enow, Qnew, h[eindex]);
-    Q = Qnew;
-  }
-  h[eindex] = Q;
-  return eindex + 1;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  grow_expansion_zeroelim()   Add a scalar to an expansion, eliminating    */
-/*                              zero components from the output expansion.   */
-/*                                                                           */
-/*  Sets h = e + b.  See the long version of my paper for details.           */
-/*                                                                           */
-/*  Maintains the nonoverlapping property.  If round-to-even is used (as     */
-/*  with IEEE 754), maintains the strongly nonoverlapping and nonadjacent    */
-/*  properties as well.  (That is, if e has one of these properties, so      */
-/*  will h.)                                                                 */
-/*                                                                           */
-/*****************************************************************************/
-
-int grow_expansion_zeroelim(int elen, const REAL *e, REAL b, REAL *h)
-/* e and h can be the same. */
-{
-  REAL Q, hh;
-  INEXACT REAL Qnew;
-  int eindex, hindex;
-  REAL enow;
-  INEXACT REAL bvirt;
-  REAL avirt, bround, around;
-
-  hindex = 0;
-  Q = b;
-  for (eindex = 0; eindex < elen; eindex++) {
-    enow = e[eindex];
-    Two_Sum(Q, enow, Qnew, hh);
-    Q = Qnew;
-    if (hh != 0.0) {
-      h[hindex++] = hh;
-    }
-  }
-  if ((Q != 0.0) || (hindex == 0)) {
-    h[hindex++] = Q;
-  }
-  return hindex;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  fast_expansion_sum()   Sum two expansions.                               */
-/*                                                                           */
-/*  Sets h = e + f.  See the long version of my paper for details.           */
-/*                                                                           */
-/*  If round-to-even is used (as with IEEE 754), maintains the strongly      */
-/*  nonoverlapping property.  (That is, if e is strongly nonoverlapping, h   */
-/*  will be also.)  Does NOT maintain the nonoverlapping or nonadjacent      */
-/*  properties.                                                              */
-/*                                                                           */
-/*****************************************************************************/
-
-int fast_expansion_sum(int elen, const REAL *e, int flen, const REAL *f, REAL *h)
-/* h cannot be e or f. */
-{
-  REAL Q;
-  INEXACT REAL Qnew;
-  INEXACT REAL bvirt;
-  REAL avirt, bround, around;
-  int eindex, findex, hindex;
-  REAL enow, fnow;
-
-  enow = e[0];
-  fnow = f[0];
-  eindex = findex = 0;
-  if ((fnow > enow) == (fnow > -enow)) {
-    Q = enow;
-    ++eindex;
-  } else {
-    Q = fnow;
-    ++findex;
-  }
-  hindex = 0;
-  if ((eindex < elen) && (findex < flen)) {
-    enow = e[eindex];
-    fnow = f[findex];
-    if ((fnow > enow) == (fnow > -enow)) {
-      Fast_Two_Sum(enow, Q, Qnew, h[0]);
-      ++eindex;
-    } else {
-      Fast_Two_Sum(fnow, Q, Qnew, h[0]);
-      ++findex;
-    }
-    Q = Qnew;
-    hindex = 1;
-    while ((eindex < elen) && (findex < flen)) {
-      enow = e[eindex];
-      fnow = f[findex];
-      if ((fnow > enow) == (fnow > -enow)) {
-        Two_Sum(Q, enow, Qnew, h[hindex]);
-        ++eindex;
-      } else {
-        Two_Sum(Q, fnow, Qnew, h[hindex]);
-        ++findex;
-      }
-      Q = Qnew;
-      hindex++;
-    }
-  }
-  while (eindex < elen) {
-    enow = e[eindex];
-    Two_Sum(Q, enow, Qnew, h[hindex]);
-    ++eindex;
-    Q = Qnew;
-    hindex++;
-  }
-  while (findex < flen) {
-    fnow = f[findex];
-    Two_Sum(Q, fnow, Qnew, h[hindex]);
-    ++findex;
-    Q = Qnew;
-    hindex++;
-  }
-  h[hindex] = Q;
-  return hindex + 1;
-}
 
 /*****************************************************************************/
 /*                                                                           */
@@ -612,7 +397,11 @@ int fast_expansion_sum(int elen, const REAL *e, int flen, const REAL *f, REAL *h
 /*                                                                           */
 /*****************************************************************************/
 
-int fast_expansion_sum_zeroelim(const int elen, const REAL *e, const int flen, const REAL *f, REAL *h)
+static int fast_expansion_sum_zeroelim(const int elen,
+                                       const REAL* const __restrict__ e,
+                                       const int flen,
+                                       const REAL* const __restrict__ f,
+                                       REAL* const __restrict__ h)
 /* h cannot be e or f. */
 {
   REAL Q;
@@ -697,49 +486,6 @@ int fast_expansion_sum_zeroelim(const int elen, const REAL *e, const int flen, c
   return hindex;
 }
 
-/*****************************************************************************/
-/*                                                                           */
-/*  scale_expansion()   Multiply an expansion by a scalar.                   */
-/*                                                                           */
-/*  Sets h = be.  See either version of my paper for details.                */
-/*                                                                           */
-/*  Maintains the nonoverlapping property.  If round-to-even is used (as     */
-/*  with IEEE 754), maintains the strongly nonoverlapping and nonadjacent    */
-/*  properties as well.  (That is, if e has one of these properties, so      */
-/*  will h.)                                                                 */
-/*                                                                           */
-/*****************************************************************************/
-
-int scale_expansion(int elen, REAL *e, REAL b, REAL *h)
-/* e and h cannot be the same. */
-{
-  INEXACT REAL Q;
-  INEXACT REAL sum;
-  INEXACT REAL product1;
-  REAL product0;
-  int eindex, hindex;
-  REAL enow;
-  INEXACT REAL bvirt;
-  REAL avirt, bround, around;
-  INEXACT REAL c;
-  INEXACT REAL abig;
-  REAL ahi, alo, bhi, blo;
-  REAL err1, err2, err3;
-
-  Split(b, bhi, blo);
-  Two_Product_Presplit(e[0], b, bhi, blo, Q, h[0]);
-  hindex = 1;
-  for (eindex = 1; eindex < elen; eindex++) {
-    enow = e[eindex];
-    Two_Product_Presplit(enow, b, bhi, blo, product1, product0);
-    Two_Sum(Q, product0, sum, h[hindex]);
-    hindex++;
-    Two_Sum(product1, sum, Q, h[hindex]);
-    hindex++;
-  }
-  h[hindex] = Q;
-  return elen + elen;
-}
 
 /*****************************************************************************/
 /*                                                                           */
@@ -756,7 +502,10 @@ int scale_expansion(int elen, REAL *e, REAL b, REAL *h)
 /*                                                                           */
 /*****************************************************************************/
 
-int scale_expansion_zeroelim(const int elen, const REAL *e, const REAL b, REAL *h)
+static int scale_expansion_zeroelim(const int elen,
+                                    const REAL* const __restrict__ e,
+                                    const REAL b,
+                                    REAL* const __restrict__ h)
 /* e and h cannot be the same. */
 {
   INEXACT REAL Q, sum;
@@ -805,7 +554,7 @@ int scale_expansion_zeroelim(const int elen, const REAL *e, const REAL b, REAL *
 /*                                                                           */
 /*****************************************************************************/
 
-static REAL estimate(const int elen, const REAL *e)
+static REAL estimate(const int elen, const REAL* const e)
 {
   REAL Q;
   int eindex;
@@ -843,18 +592,21 @@ static REAL estimate(const int elen, const REAL *e)
 /*                                                                           */
 /*****************************************************************************/
 
-REAL orient2dfast(const REAL* __restrict__ pa, const REAL* __restrict__ pb, const REAL* __restrict__ pc)
-{
-  REAL acx, bcx, acy, bcy;
-
-  acx = pa[0] - pc[0];
-  bcx = pb[0] - pc[0];
-  acy = pa[1] - pc[1];
-  bcy = pb[1] - pc[1];
-  return acx * bcy - acy * bcx;
-}
-
-REAL orient2dadapt(const REAL* __restrict__ pa, const REAL* __restrict__ pb, const REAL* __restrict__ pc, const REAL detsum)
+// REAL orient2dfast(const REAL* const __restrict__ pa, const REAL* const __restrict__ pb, const REAL* const __restrict__ pc)
+// {
+//   REAL acx, bcx, acy, bcy;
+
+//   acx = pa[0] - pc[0];
+//   bcx = pb[0] - pc[0];
+//   acy = pa[1] - pc[1];
+//   bcy = pb[1] - pc[1];
+//   return acx * bcy - acy * bcx;
+// }
+
+static REAL orient2dadapt(const REAL* const __restrict__ pa,
+                          const REAL* const __restrict__ pb,
+                          const REAL* const __restrict__ pc,
+                          const REAL detsum)
 {
   INEXACT REAL acx, acy, bcx, bcy;
   REAL acxtail, acytail, bcxtail, bcytail;
@@ -934,7 +686,7 @@ REAL orient2dadapt(const REAL* __restrict__ pa, const REAL* __restrict__ pb, con
   return(D[Dlength - 1]);
 }
 
-REAL orient2d(const REAL* __restrict__ pa, const REAL* __restrict__ pb, const REAL* __restrict__ pc)
+REAL orient2d(const REAL* const __restrict__ pa, const REAL* const __restrict__ pb, const REAL* const __restrict__ pc)
 {
   REAL detleft, detright, det;
   REAL detsum, errbound;
@@ -997,7 +749,11 @@ REAL orient2d(const REAL* __restrict__ pa, const REAL* __restrict__ pb, const RE
 /*****************************************************************************/
 
 
-static REAL orient3dadapt(const REAL* __restrict__ pa, const REAL* __restrict__ pb, const REAL* __restrict__ pc, const REAL* __restrict__ pd, const REAL permanent)
+static REAL orient3dadapt(const REAL* const __restrict__ pa,
+                          const REAL* const __restrict__ pb,
+                          const REAL* const __restrict__ pc,
+                          const REAL* const __restrict__ pd,
+                          const REAL permanent)
 {
   INEXACT REAL adx, bdx, cdx, ady, bdy, cdy, adz, bdz, cdz;
   REAL det, errbound;
@@ -1409,7 +1165,10 @@ static REAL orient3dadapt(const REAL* __restrict__ pa, const REAL* __restrict__
 }
 
 
-REAL orient3d(const REAL* const __restrict__ pa, const REAL* const __restrict__ pb, const REAL* const __restrict__ pc, const REAL* const __restrict__ pd)
+REAL orient3d(const REAL* const __restrict__ pa,
+              const REAL* const __restrict__ pb,
+              const REAL* const __restrict__ pc,
+              const REAL* const __restrict__ pd)
 {
   // return orient3dexact(pa, pb, pc, pd);
 
@@ -1485,30 +1244,37 @@ REAL orient3d(const REAL* const __restrict__ pa, const REAL* const __restrict__
 /*                                                                           */
 /*****************************************************************************/
 
-REAL incirclefast(const REAL* __restrict__ pa, const REAL* __restrict__ pb, const REAL* __restrict__ pc, const REAL* __restrict__ pd)
-{
-  REAL adx, ady, bdx, bdy, cdx, cdy;
-  REAL abdet, bcdet, cadet;
-  REAL alift, blift, clift;
-
-  adx = pa[0] - pd[0];
-  ady = pa[1] - pd[1];
-  bdx = pb[0] - pd[0];
-  bdy = pb[1] - pd[1];
-  cdx = pc[0] - pd[0];
-  cdy = pc[1] - pd[1];
-
-  abdet = adx * bdy - bdx * ady;
-  bcdet = bdx * cdy - cdx * bdy;
-  cadet = cdx * ady - adx * cdy;
-  alift = adx * adx + ady * ady;
-  blift = bdx * bdx + bdy * bdy;
-  clift = cdx * cdx + cdy * cdy;
-
-  return alift * bcdet + blift * cadet + clift * abdet;
-}
-
-REAL incircleadapt(const REAL* __restrict__ pa, const REAL* __restrict__ pb, const REAL* __restrict__ pc, const REAL* __restrict__ pd, const REAL permanent)
+// REAL incirclefast(const REAL* const __restrict__ pa,
+//                   const REAL* const __restrict__ pb,
+//                   const REAL* const __restrict__ pc,
+//                   const REAL* const __restrict__ pd)
+// {
+//   REAL adx, ady, bdx, bdy, cdx, cdy;
+//   REAL abdet, bcdet, cadet;
+//   REAL alift, blift, clift;
+
+//   adx = pa[0] - pd[0];
+//   ady = pa[1] - pd[1];
+//   bdx = pb[0] - pd[0];
+//   bdy = pb[1] - pd[1];
+//   cdx = pc[0] - pd[0];
+//   cdy = pc[1] - pd[1];
+
+//   abdet = adx * bdy - bdx * ady;
+//   bcdet = bdx * cdy - cdx * bdy;
+//   cadet = cdx * ady - adx * cdy;
+//   alift = adx * adx + ady * ady;
+//   blift = bdx * bdx + bdy * bdy;
+//   clift = cdx * cdx + cdy * cdy;
+
+//   return alift * bcdet + blift * cadet + clift * abdet;
+// }
+
+static REAL incircleadapt(const REAL* const __restrict__ pa,
+                          const REAL* const __restrict__ pb,
+                          const REAL* const __restrict__ pc,
+                          const REAL* const __restrict__ pd,
+                          const REAL permanent)
 {
   INEXACT REAL adx, bdx, cdx, ady, bdy, cdy;
   REAL det, errbound;
@@ -2080,7 +1846,10 @@ REAL incircleadapt(const REAL* __restrict__ pa, const REAL* __restrict__ pb, con
   return finnow[finlength - 1];
 }
 
-REAL incircle(const REAL* __restrict__ pa, const REAL* __restrict__ pb, const REAL* __restrict__ pc, const REAL* __restrict__ pd)
+REAL incircle(const REAL* const __restrict__ pa,
+              const REAL* const __restrict__ pb,
+              const REAL* const __restrict__ pc,
+              const REAL* const __restrict__ pd)
 {
   REAL adx, bdx, cdx, ady, bdy, cdy;
   REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
@@ -2149,50 +1918,54 @@ REAL incircle(const REAL* __restrict__ pa, const REAL* __restrict__ pb, const RE
 /*                                                                           */
 /*****************************************************************************/
 
-REAL inspherefast(const REAL* const __restrict__ pa, const REAL* const __restrict__ pb, const REAL* const __restrict__ pc, const REAL* const __restrict__ pd, const REAL* const __restrict__ pe)
-{
-  REAL aex, bex, cex, dex;
-  REAL aey, bey, cey, dey;
-  REAL aez, bez, cez, dez;
-  REAL alift, blift, clift, dlift;
-  REAL ab, bc, cd, da, ac, bd;
-  REAL abc, bcd, cda, dab;
-
-  aex = pa[0] - pe[0];
-  bex = pb[0] - pe[0];
-  cex = pc[0] - pe[0];
-  dex = pd[0] - pe[0];
-  aey = pa[1] - pe[1];
-  bey = pb[1] - pe[1];
-  cey = pc[1] - pe[1];
-  dey = pd[1] - pe[1];
-  aez = pa[2] - pe[2];
-  bez = pb[2] - pe[2];
-  cez = pc[2] - pe[2];
-  dez = pd[2] - pe[2];
-
-  ab = aex * bey - bex * aey;
-  bc = bex * cey - cex * bey;
-  cd = cex * dey - dex * cey;
-  da = dex * aey - aex * dey;
-
-  ac = aex * cey - cex * aey;
-  bd = bex * dey - dex * bey;
-
-  abc = aez * bc - bez * ac + cez * ab;
-  bcd = bez * cd - cez * bd + dez * bc;
-  cda = cez * da + dez * ac + aez * cd;
-  dab = dez * ab + aez * bd + bez * da;
-
-  alift = aex * aex + aey * aey + aez * aez;
-  blift = bex * bex + bey * bey + bez * bez;
-  clift = cex * cex + cey * cey + cez * cez;
-  dlift = dex * dex + dey * dey + dez * dez;
-
-  return (dlift * abc - clift * dab) + (blift * cda - alift * bcd);
-}
-
-REAL insphereexact(const REAL* const __restrict__ pa, const REAL* const __restrict__ pb, const REAL* const __restrict__ pc, const REAL* const __restrict__ pd, const REAL* const __restrict__ pe)
+// REAL inspherefast(const REAL* const __restrict__ pa, const REAL* const __restrict__ pb, const REAL* const __restrict__ pc, const REAL* const __restrict__ pd, const REAL* const __restrict__ pe)
+// {
+//   REAL aex, bex, cex, dex;
+//   REAL aey, bey, cey, dey;
+//   REAL aez, bez, cez, dez;
+//   REAL alift, blift, clift, dlift;
+//   REAL ab, bc, cd, da, ac, bd;
+//   REAL abc, bcd, cda, dab;
+
+//   aex = pa[0] - pe[0];
+//   bex = pb[0] - pe[0];
+//   cex = pc[0] - pe[0];
+//   dex = pd[0] - pe[0];
+//   aey = pa[1] - pe[1];
+//   bey = pb[1] - pe[1];
+//   cey = pc[1] - pe[1];
+//   dey = pd[1] - pe[1];
+//   aez = pa[2] - pe[2];
+//   bez = pb[2] - pe[2];
+//   cez = pc[2] - pe[2];
+//   dez = pd[2] - pe[2];
+
+//   ab = aex * bey - bex * aey;
+//   bc = bex * cey - cex * bey;
+//   cd = cex * dey - dex * cey;
+//   da = dex * aey - aex * dey;
+
+//   ac = aex * cey - cex * aey;
+//   bd = bex * dey - dex * bey;
+
+//   abc = aez * bc - bez * ac + cez * ab;
+//   bcd = bez * cd - cez * bd + dez * bc;
+//   cda = cez * da + dez * ac + aez * cd;
+//   dab = dez * ab + aez * bd + bez * da;
+
+//   alift = aex * aex + aey * aey + aez * aez;
+//   blift = bex * bex + bey * bey + bez * bez;
+//   clift = cex * cex + cey * cey + cez * cez;
+//   dlift = dex * dex + dey * dey + dez * dez;
+
+//   return (dlift * abc - clift * dab) + (blift * cda - alift * bcd);
+// }
+
+static REAL insphereexact(const REAL* const __restrict__ pa,
+                          const REAL* const __restrict__ pb,
+                          const REAL* const __restrict__ pc,
+                          const REAL* const __restrict__ pd,
+                          const REAL* const __restrict__ pe)
 {
   INEXACT REAL axby1, bxcy1, cxdy1, dxey1, exay1;
   INEXACT REAL bxay1, cxby1, dxcy1, exdy1, axey1;
@@ -2446,8 +2219,12 @@ REAL insphereexact(const REAL* const __restrict__ pa, const REAL* const __restri
 }
 
 
-REAL insphereadapt(const REAL* const __restrict__ pa, const REAL* const __restrict__ pb, const REAL* const __restrict__ pc, const REAL* const __restrict__ pd, const REAL* const __restrict__ pe,
-                   const REAL permanent)
+static REAL insphereadapt(const REAL* const __restrict__ pa,
+                          const REAL* const __restrict__ pb,
+                          const REAL* const __restrict__ pc,
+                          const REAL* const __restrict__ pd,
+                          const REAL* const __restrict__ pe,
+                          const REAL permanent)
 {
   INEXACT REAL aex, bex, cex, dex, aey, bey, cey, dey, aez, bez, cez, dez;
   REAL det, errbound;
@@ -2664,7 +2441,11 @@ REAL insphereadapt(const REAL* const __restrict__ pa, const REAL* const __restri
 }
 
 
-REAL insphere(const REAL* const __restrict__ pa, const REAL* const __restrict__ pb, const REAL* const __restrict__ pc, const REAL* const __restrict__ pd, const REAL* const __restrict__ pe)
+REAL insphere(const REAL* const __restrict__ pa,
+              const REAL* const __restrict__ pb,
+              const REAL* const __restrict__ pc,
+              const REAL* const __restrict__ pd,
+              const REAL* const __restrict__ pe)
 {
   REAL aex, bex, cex, dex;
   REAL aey, bey, cey, dey;
diff --git a/contrib/hxt/reparam/CMakeLists.txt b/contrib/hxt/reparam/CMakeLists.txt
new file mode 100644
index 0000000000..498faf3150
--- /dev/null
+++ b/contrib/hxt/reparam/CMakeLists.txt
@@ -0,0 +1,46 @@
+cmake_minimum_required(VERSION 3.9)
+project(hxt_reparam C)
+
+# most options are inherited from hxt_core (see ../core/CMakeList.txt)
+
+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)
+
+set(HXT_REPARAM_SRC
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_edge.c"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_curvature.c"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_mean_values.c"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_linear_system.c"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_linear_system_lu.c"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_non_linear_solver.c"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_linear_system_petsc.c"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_class_macro.h"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_linear_system_lu.h"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_non_linear_solver.h"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_linear_system_petsc.h"
+    "${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"
+   )
+
+if(HXT_REPARAM_OBJECT_ONLY)
+  add_library(hxt_reparam OBJECT ${HXT_REPARAM_SRC})
+else()
+  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_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)
+endif()
+
diff --git a/contrib/hxt/reparam/cmake/FindPETSc.cmake b/contrib/hxt/reparam/cmake/FindPETSc.cmake
new file mode 100644
index 0000000000..c566e20bcb
--- /dev/null
+++ b/contrib/hxt/reparam/cmake/FindPETSc.cmake
@@ -0,0 +1,119 @@
+# - Try to find PETSc
+# Once done this will define
+#
+#  PETSC_INC     - the PETSc include directories
+#  PETSC_LIBS    - Link these to use PETSc
+
+macro(find_all_libraries VARNAME LISTNAME PATH SUFFIX)
+  set(${VARNAME})
+  list(LENGTH ${LISTNAME} NUM_LIST)
+  foreach(LIB ${${LISTNAME}})
+    if("${PATH}" STREQUAL "")
+      find_library(FOUND_LIB ${LIB} PATH_SUFFIXES ${SUFFIX})
+    else("${PATH}" STREQUAL "")
+      find_library(FOUND_LIB ${LIB} PATHS ${PATH} NO_DEFAULT_PATH)
+    endif("${PATH}" STREQUAL "")
+    if(FOUND_LIB)
+      list(APPEND ${VARNAME} ${FOUND_LIB})
+    endif(FOUND_LIB)
+    unset(FOUND_LIB CACHE)
+  endforeach(LIB)
+  list(LENGTH ${VARNAME} NUM_FOUND_LIBRARIES)
+  if(NUM_FOUND_LIBRARIES LESS NUM_LIST)
+    set(${VARNAME})
+  endif(NUM_FOUND_LIBRARIES LESS NUM_LIST)
+endmacro(find_all_libraries)
+
+
+if(PETSC_DIR)
+  set(ENV_PETSC_DIR ${PETSC_DIR})
+else(PETSC_DIR)
+  set(ENV_PETSC_DIR $ENV{PETSC_DIR})
+endif(PETSC_DIR)
+if(PETSC_ARCH)
+  set(ENV_PETSC_ARCH ${PETSC_ARCH})
+else(PETSC_ARCH)
+  set(ENV_PETSC_ARCH $ENV{PETSC_ARCH})
+endif(PETSC_ARCH)
+set(PETSC_POSSIBLE_CONF_FILES 
+    ${ENV_PETSC_DIR}/${ENV_PETSC_ARCH}/conf/petscvariables
+    ${ENV_PETSC_DIR}/${ENV_PETSC_ARCH}/lib/petsc-conf/petscvariables
+    ${ENV_PETSC_DIR}/${ENV_PETSC_ARCH}/lib/petsc/conf/petscvariables)
+foreach(FILE ${PETSC_POSSIBLE_CONF_FILES})
+  if(EXISTS ${FILE})
+    # old-style PETSc installations (using PETSC_DIR and PETSC_ARCH)
+    message(STATUS "Using PETSc dir: ${ENV_PETSC_DIR}")
+    message(STATUS "Using PETSc arch: ${ENV_PETSC_ARCH}")
+    # find includes by parsing the petscvariables file
+    file(STRINGS ${FILE} PETSC_VARIABLES NEWLINE_CONSUME)
+  endif(EXISTS ${FILE})
+endforeach(FILE)
+if(PETSC_VARIABLES)
+  # try to find PETSC_CC_INCLUDES for PETSc >= 3.4
+  string(REGEX MATCH "PETSC_CC_INCLUDES = [^\n\r]*" PETSC_PACKAGES_INCLUDES
+         ${PETSC_VARIABLES})
+  if(PETSC_PACKAGES_INCLUDES)
+    string(REPLACE "PETSC_CC_INCLUDES = " "" PETSC_PACKAGES_INCLUDES
+           ${PETSC_PACKAGES_INCLUDES})
+  else(PETSC_PACKAGES_INCLUDES)
+    # try to find PETSC_PACKAGES_INCLUDES in older versions
+    list(APPEND PETSC_INC ${ENV_PETSC_DIR}/include)
+    list(APPEND PETSC_INC ${ENV_PETSC_DIR}/${ENV_PETSC_ARCH}/include)
+    string(REGEX MATCH "PACKAGES_INCLUDES = [^\n\r]*" PETSC_PACKAGES_INCLUDES
+           ${PETSC_VARIABLES})
+    string(REPLACE "PACKAGES_INCLUDES = " "" PETSC_PACKAGES_INCLUDES
+           ${PETSC_PACKAGES_INCLUDES})
+  endif(PETSC_PACKAGES_INCLUDES)
+  if(PETSC_PACKAGES_INCLUDES)
+    if(PETSC_PACKAGES_INCLUDES)
+      string(REPLACE "-I" "" PETSC_PACKAGES_INCLUDES ${PETSC_PACKAGES_INCLUDES})
+      string(REPLACE " " ";" PETSC_PACKAGES_INCLUDES ${PETSC_PACKAGES_INCLUDES})
+      foreach(VAR ${PETSC_PACKAGES_INCLUDES})
+        # seem to include unexisting directories (/usr/include/lib64)
+  # check to avoid warnings
+  if(EXISTS ${VAR})
+    list(APPEND PETSC_INC ${VAR})
+        endif(EXISTS ${VAR})
+      endforeach(VAR)
+    endif(PETSC_PACKAGES_INCLUDES)
+  endif(PETSC_PACKAGES_INCLUDES)
+  # find libraries (<= 3.0)
+  set(PETSC_LIBS_REQUIRED petscksp petscdm petscmat petscvec petsc)
+  find_all_libraries(PETSC_LIBS PETSC_LIBS_REQUIRED
+                     ${ENV_PETSC_DIR}/${ENV_PETSC_ARCH}/lib "")
+  # petsc 3.1 creates only one library (libpetsc)
+  if(NOT PETSC_LIBS)
+    find_library(PETSC_LIBS petsc PATHS ${ENV_PETSC_DIR}/${ENV_PETSC_ARCH}/lib
+                 NO_DEFAULT_PATH)
+  endif(NOT PETSC_LIBS)
+  # find additional libraries to link with
+  string(REGEX MATCH "PACKAGES_LIBS = [^\n\r]*" PLIBS ${PETSC_VARIABLES})
+  if(PLIBS)
+    string(REPLACE "PACKAGES_LIBS = " "" PLIBS ${PLIBS})
+    string(STRIP ${PLIBS} PLIBS)
+    list(APPEND PETSC_LIBS "${PLIBS}")
+  endif(PLIBS)
+  string(REGEX MATCH "PETSC_EXTERNAL_LIB_BASIC = [^\n\r]*" PLIBS_BASIC ${PETSC_VARIABLES})
+  if(PLIBS_BASIC)
+    string(REPLACE "PETSC_EXTERNAL_LIB_BASIC = " "" PLIBS_BASIC ${PLIBS_BASIC})
+    string(STRIP ${PLIBS_BASIC} PLIBS_BASIC)
+    separate_arguments(PLIBS_BASIC)
+    list(APPEND PETSC_LIBS "${PLIBS_BASIC}")
+  endif(PLIBS_BASIC)
+  string(REGEX MATCH "PCC_LINKER_LIBS = [^\n\r]*" LLIBS ${PETSC_VARIABLES})
+  if(LLIBS)
+    string(REPLACE "PCC_LINKER_LIBS = " "" LLIBS ${LLIBS})
+    string(STRIP ${LLIBS} LLIBS)
+    list(APPEND PETSC_LIBS "${LLIBS}")
+  endif(LLIBS)
+else(PETSC_VARIABLES)
+  # new-style PETSc installations (in standard system directories)
+  find_library(PETSC_LIBS petsc)
+  find_path(PETSC_INC "petsc.h" PATH_SUFFIXES include/petsc)
+endif(PETSC_VARIABLES)
+
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(PETSc DEFAULT_MSG PETSC_LIBS PETSC_INC)
+mark_as_advanced(PETSC_LIBS PETSC_INC)
+
diff --git a/contrib/hxt/hxt_curvature.h b/contrib/hxt/reparam/include/hxt_curvature.h
similarity index 100%
rename from contrib/hxt/hxt_curvature.h
rename to contrib/hxt/reparam/include/hxt_curvature.h
diff --git a/contrib/hxt/hxt_edge.h b/contrib/hxt/reparam/include/hxt_edge.h
similarity index 97%
rename from contrib/hxt/hxt_edge.h
rename to contrib/hxt/reparam/include/hxt_edge.h
index 11a2cf7a14..8857d9b0c4 100644
--- a/contrib/hxt/hxt_edge.h
+++ b/contrib/hxt/reparam/include/hxt_edge.h
@@ -1,9 +1,7 @@
 #ifndef HEXTREME_EDGE_H
 #define HEXTREME_EDGE_H
 
-#include "hxt_tools.h"
 #include "hxt_mesh.h"
-#include <math.h>
 
 typedef struct hxtLineLoopStruct HXTLineLoop;
 
diff --git a/contrib/hxt/hxt_linear_system.h b/contrib/hxt/reparam/include/hxt_linear_system.h
similarity index 98%
rename from contrib/hxt/hxt_linear_system.h
rename to contrib/hxt/reparam/include/hxt_linear_system.h
index 133380cb2d..23faf30798 100644
--- a/contrib/hxt/hxt_linear_system.h
+++ b/contrib/hxt/reparam/include/hxt_linear_system.h
@@ -1,7 +1,8 @@
 #ifndef HEXTREME_LINEAR_SYSTEM_H
 #define HEXTREME_LINEAR_SYSTEM_H
+
 #include <stdint.h>
-#include "hxt_api.h"
+#include "hxt_message.h"
 
 typedef struct HXTLinearSystemStruct HXTLinearSystem;
 
diff --git a/contrib/hxt/hxt_mean_values.h b/contrib/hxt/reparam/include/hxt_mean_values.h
similarity index 95%
rename from contrib/hxt/hxt_mean_values.h
rename to contrib/hxt/reparam/include/hxt_mean_values.h
index fcbf246ffc..05916f6e40 100644
--- a/contrib/hxt/hxt_mean_values.h
+++ b/contrib/hxt/reparam/include/hxt_mean_values.h
@@ -12,7 +12,10 @@ HXTStatus hxtMeanValuesDelete(HXTMeanValues **meanValues);
 HXTStatus hxtMeanValuesCompute(HXTMeanValues *meanValues);
 HXTStatus hxtMeanValueAspectRatio(HXTMeanValues *meanValues, int *aspectRatio);
 HXTStatus hxtMeanValuesGetData(HXTMeanValues *mv, uint64_t **global, uint32_t **gn, double **uv, int *nv, int *ne, int onlyuv);
+
+#ifdef HXT_CORE_FILEIO
 HXTStatus hxtMeanValuesWrite(HXTMeanValues *meanValues, const char* filename);
 HXTStatus hxtMeanValuesWriteParamMesh(HXTMeanValues *meanValues, const char* filename);
+#endif
 
 #endif
diff --git a/contrib/hxt/hxt_class_macro.h b/contrib/hxt/reparam/src/hxt_class_macro.h
similarity index 100%
rename from contrib/hxt/hxt_class_macro.h
rename to contrib/hxt/reparam/src/hxt_class_macro.h
diff --git a/contrib/hxt/hxt_curvature.c b/contrib/hxt/reparam/src/hxt_curvature.c
similarity index 81%
rename from contrib/hxt/hxt_curvature.c
rename to contrib/hxt/reparam/src/hxt_curvature.c
index f38bcb81ad..9ebd686f47 100644
--- a/contrib/hxt/hxt_curvature.c
+++ b/contrib/hxt/reparam/src/hxt_curvature.c
@@ -1,8 +1,47 @@
-#include <math.h>
-#include <time.h>
 #include "hxt_curvature.h"
+#include "hxt_tools.h"
+#include <math.h>
+#include <stdio.h>
+
+// #include <time.h> // for commented timings
+
 
 #define tolerance 0.1e-20
+
+static HXTStatus hxtInv4x4ColumnMajor(double m[16], double invOut[16], double *det)
+{
+  double inv[16];
+  int i;
+  
+  inv[ 0] =  m[5] * m[10] * m[15] - m[5] * m[11] * m[14] - m[9] * m[6] * m[15] + m[9] * m[7] * m[14] + m[13] * m[6] * m[11] - m[13] * m[7] * m[10];
+  inv[ 4] = -m[4] * m[10] * m[15] + m[4] * m[11] * m[14] + m[8] * m[6] * m[15] - m[8] * m[7] * m[14] - m[12] * m[6] * m[11] + m[12] * m[7] * m[10];
+  inv[ 8] =  m[4] * m[ 9] * m[15] - m[4] * m[11] * m[13] - m[8] * m[5] * m[15] + m[8] * m[7] * m[13] + m[12] * m[5] * m[11] - m[12] * m[7] * m[ 9];
+  inv[12] = -m[4] * m[ 9] * m[14] + m[4] * m[10] * m[13] + m[8] * m[5] * m[14] - m[8] * m[6] * m[13] - m[12] * m[5] * m[10] + m[12] * m[6] * m[ 9];
+  inv[ 1] = -m[1] * m[10] * m[15] + m[1] * m[11] * m[14] + m[9] * m[2] * m[15] - m[9] * m[3] * m[14] - m[13] * m[2] * m[11] + m[13] * m[3] * m[10];
+  inv[ 5] =  m[0] * m[10] * m[15] - m[0] * m[11] * m[14] - m[8] * m[2] * m[15] + m[8] * m[3] * m[14] + m[12] * m[2] * m[11] - m[12] * m[3] * m[10];
+  inv[ 9] = -m[0] * m[ 9] * m[15] + m[0] * m[11] * m[13] + m[8] * m[1] * m[15] - m[8] * m[3] * m[13] - m[12] * m[1] * m[11] + m[12] * m[3] * m[ 9];
+  inv[13] =  m[0] * m[ 9] * m[14] - m[0] * m[10] * m[13] - m[8] * m[1] * m[14] + m[8] * m[2] * m[13] + m[12] * m[1] * m[10] - m[12] * m[2] * m[ 9];
+  inv[ 2] =  m[1] * m[ 6] * m[15] - m[1] * m[ 7] * m[14] - m[5] * m[2] * m[15] + m[5] * m[3] * m[14] + m[13] * m[2] * m[ 7] - m[13] * m[3] * m[ 6];
+  inv[ 6] = -m[0] * m[ 6] * m[15] + m[0] * m[ 7] * m[14] + m[4] * m[2] * m[15] - m[4] * m[3] * m[14] - m[12] * m[2] * m[ 7] + m[12] * m[3] * m[ 6];
+  inv[10] =  m[0] * m[ 5] * m[15] - m[0] * m[ 7] * m[13] - m[4] * m[1] * m[15] + m[4] * m[3] * m[13] + m[12] * m[1] * m[ 7] - m[12] * m[3] * m[ 5];
+  inv[14] = -m[0] * m[ 5] * m[14] + m[0] * m[ 6] * m[13] + m[4] * m[1] * m[14] - m[4] * m[2] * m[13] - m[12] * m[1] * m[ 6] + m[12] * m[2] * m[ 5];
+  inv[ 3] = -m[1] * m[ 6] * m[11] + m[1] * m[ 7] * m[10] + m[5] * m[2] * m[11] - m[5] * m[3] * m[10] - m[ 9] * m[2] * m[ 7] + m[ 9] * m[3] * m[ 6];
+  inv[ 7] =  m[0] * m[ 6] * m[11] - m[0] * m[ 7] * m[10] - m[4] * m[2] * m[11] + m[4] * m[3] * m[10] + m[ 8] * m[2] * m[ 7] - m[ 8] * m[3] * m[ 6];
+  inv[11] = -m[0] * m[ 5] * m[11] + m[0] * m[ 7] * m[ 9] + m[4] * m[1] * m[11] - m[4] * m[3] * m[ 9] - m[ 8] * m[1] * m[ 7] + m[ 8] * m[3] * m[ 5];
+  inv[15] =  m[0] * m[ 5] * m[10] - m[0] * m[ 6] * m[ 9] - m[4] * m[1] * m[10] + m[4] * m[2] * m[ 9] + m[ 8] * m[1] * m[ 6] - m[ 8] * m[2] * m[ 5];
+  
+  *det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12];
+  
+  if(*det == 0)
+    return HXT_STATUS_ERROR;
+    
+  double invDet = 1.0 / *det;
+  
+  for(i = 0; i < 16; i++)
+    invOut[i] = inv[i] * invDet;
+  
+  return HXT_STATUS_OK;
+}
  
 static void solveEig(double A, double B, double C, double D, 
                       double* lambda1, double *v1x, double*v1y, 
@@ -43,8 +82,8 @@ static void solveEig(double A, double B, double C, double D,
 
 static inline int node2trianglescmp(const void *p0, const void *p1)
 { 
-  uint64_t *e0 = (uint64_t*)p0;
-  uint64_t *e1 = (uint64_t*)p1;
+  const uint64_t *e0 = (const uint64_t*)p0;
+  const uint64_t *e1 = (const uint64_t*)p1;
   
   if (e0[0] < e1[0]) return -1;
   if (e0[0] > e1[0]) return  1;
@@ -135,14 +174,14 @@ void saveNodalField (HXTMesh *mesh, double *v, int ncomp, const char *fn){
               p0[0],p0[1],p0[2],p1[0],p1[1],p1[2],p2[0],p2[1],p2[2],
               v0[3],v0[4],v0[5],v1[3],v1[4],v1[5],v2[3],v2[4],v2[5]);
   }  
- fprintf(f,"};\n");
+  fprintf(f,"};\n");
   
   fclose (f);
 }
 
 HXTStatus hxtCurvatureRusinkiewicz (HXTMesh *mesh, double **nodalCurvatures, double **crossField, HXTEdges* edges, int debug)
 {
-  clock_t T1 = clock();
+  // clock_t T1 = clock();
   
   uint64_t nTriangles  = mesh->triangles.num;
   //  uint64_t nEdgesBdry = mesh->lines.num;
@@ -370,7 +409,7 @@ HXTStatus hxtCurvatureRusinkiewicz (HXTMesh *mesh, double **nodalCurvatures, dou
   HXT_CHECK(hxtFree(&nodeNormals)); 
   HXT_CHECK(hxtFree(&CURV)); 
 
-  clock_t T2 = clock();
+  // clock_t T2 = clock();
 
   
   //  HXT_INFO ("Curvature has been computed for %u vertices in %8.4f seconds",nVertices,(double)(T2-T1)/CLOCKS_PER_SEC);
diff --git a/contrib/hxt/hxt_edge.c b/contrib/hxt/reparam/src/hxt_edge.c
similarity index 98%
rename from contrib/hxt/hxt_edge.c
rename to contrib/hxt/reparam/src/hxt_edge.c
index ea53381250..99538a974a 100644
--- a/contrib/hxt/hxt_edge.c
+++ b/contrib/hxt/reparam/src/hxt_edge.c
@@ -1,4 +1,7 @@
 #include "hxt_edge.h"
+#include "hxt_tools.h"
+#include <string.h>
+#include <math.h>
 
 struct hxtLineLoopStruct{
   double length;
@@ -33,9 +36,9 @@ double hxtEdgesLength(const HXTEdges *edges,uint32_t ie){
 
 static inline int halfedgecmp(const void *p0, const void *p1)
 { 
-  uint32_t *e0 = (uint32_t*)p0;
+  const uint32_t *e0 = (const uint32_t*)p0;
   uint32_t es0[2] = {e0[0] < e0[1] ? e0[0] : e0[1], e0[0] < e0[1] ? e0[1] : e0[0]};
-  uint32_t *e1 = (uint32_t*)p1;
+  const uint32_t *e1 = (const uint32_t*)p1;
   uint32_t es1[2] = {e1[0] < e1[1] ? e1[0] : e1[1], e1[0] < e1[1] ? e1[1] : e1[0]};
 
   if (es0[0] < es1[0]) return -1;
@@ -183,7 +186,7 @@ HXTStatus hxtEdgesSetBoundaries(HXTEdges *edges, HXTBoundaries **boundaries)
   HXT_CHECK(hxtFree(&firstNode2Edge));
   lineLoops->nbedg = nbBorder;
   if(lineLoops->seamPoint==1){
-    printf("SEAM POINT!!!!\n");
+    HXT_WARNING("SEAM POINT!!!!\n");
     lineLoops->nll=-1;
     lineLoops->lineLoop = NULL;
     return HXT_STATUS_OK;	
diff --git a/contrib/hxt/hxt_linear_system.c b/contrib/hxt/reparam/src/hxt_linear_system.c
similarity index 96%
rename from contrib/hxt/hxt_linear_system.c
rename to contrib/hxt/reparam/src/hxt_linear_system.c
index 7105062d2f..61d3759f27 100644
--- a/contrib/hxt/hxt_linear_system.c
+++ b/contrib/hxt/reparam/src/hxt_linear_system.c
@@ -27,6 +27,11 @@ HXT_DECLARE_DERIVED_CLASS(LinearSystem, LinearSystemPETSc)
 #endif
 
 HXTStatus hxtInitializeLinearSystems(int *argc, char ***argv) {
+#ifndef HXT_HAVE_PETSC
+  HXT_UNUSED(argc);
+  HXT_UNUSED(argv);
+#endif
+
   HXT_CHECK(hxtLinearSystemLURegister());
 #ifdef HXT_HAVE_PETSC
   HXT_CHECK(hxtInitializePETSc(argc, argv));
diff --git a/contrib/hxt/hxt_linear_system_lu.c b/contrib/hxt/reparam/src/hxt_linear_system_lu.c
similarity index 77%
rename from contrib/hxt/hxt_linear_system_lu.c
rename to contrib/hxt/reparam/src/hxt_linear_system_lu.c
index 51a40453e8..6fcc926e33 100644
--- a/contrib/hxt/hxt_linear_system_lu.c
+++ b/contrib/hxt/reparam/src/hxt_linear_system_lu.c
@@ -8,16 +8,16 @@
 //#define CONMAX 2000
 
 #ifdef CONMAX
-static void connectivityInsert(int *connectivity, int i, int j)
+static HXTStatus connectivityInsert(int *connectivity, int i, int j)
 {
   for (int k = 0; k < CONMAX; ++k) {
     int *p = connectivity + CONMAX*i + k;
     if (*p == -1)
       *p = j;
     if (*p == j)
-      return;
+      return HXT_STATUS_OK;
   }
-  printf("ERROR : node %i has more than %i neighbours\n", i, CONMAX);
+  return HXT_ERROR_MSG(HXT_STATUS_ERROR, "node %i has more than %i neighbours\n", i, CONMAX);
 }
 #endif
 
@@ -46,57 +46,61 @@ struct HXTConnectivity {
   int **nodeConnectivity;
 };
 
-void mallocConnectivity (struct HXTConnectivity *c, int n, int q)
+static HXTStatus allocConnectivity (struct HXTConnectivity *c, int n, int q)
 {
-  c-> nNodes = n;
-  c-> quantum = q;
-  c-> allocated        = malloc (sizeof(int) * c->nNodes);
-  c-> degree           = malloc (sizeof(int) * c->nNodes);
-  c-> nodeConnectivity = malloc (sizeof(int*)* c->nNodes);
+  c->nNodes = n;
+  c->quantum = q;
+  HXT_CHECK( hxtMalloc(&c->allocated,        sizeof(int) * c->nNodes) );
+  HXT_CHECK( hxtMalloc(&c->degree,           sizeof(int) * c->nNodes) );
+  HXT_CHECK( hxtMalloc(&c->nodeConnectivity, sizeof(int) * c->nNodes) );
   for (int i=0;i<c->nNodes;i++){
-    c-> allocated[i] = c->quantum;
-    c-> degree [i] = 0;
-    c-> nodeConnectivity [i] = malloc (sizeof(int) * c-> allocated[i]);
+    c->allocated[i] = c->quantum;
+    c->degree [i] = 0;
+    HXT_CHECK( hxtMalloc(&c->nodeConnectivity[i], sizeof(int) * c-> allocated[i]) );
   }
+  return HXT_STATUS_OK;
 }
 
-void freeConnectivity (struct HXTConnectivity *c)
+static HXTStatus freeConnectivity (struct HXTConnectivity *c)
 {
   for (int i=0;i<c->nNodes;i++){
-    free(c-> nodeConnectivity [i]);
+    HXT_CHECK( hxtFree(&c->nodeConnectivity[i]) );
   }
-  free(c-> nodeConnectivity);
-  free(c-> degree);
-  free(c-> allocated);
+  HXT_CHECK( hxtFree(&c->nodeConnectivity) );
+  HXT_CHECK( hxtFree(&c->degree) );
+  HXT_CHECK( hxtFree(&c->allocated) );
   c-> nNodes = 0;
+  return HXT_STATUS_OK;
 }
 
 
-int addToConnectivity (struct HXTConnectivity *c, int myRow, int myCol){
-  if (myRow >= c->nNodes) return -1;
+static HXTStatus addToConnectivity (struct HXTConnectivity *c, int myRow, int myCol){
+  if (myRow >= c->nNodes) return HXT_ERROR(HXT_STATUS_ERROR);
 
   if (c->allocated[myRow] == c->degree[myRow]){
     c->allocated[myRow]*= 2;
-    c-> nodeConnectivity [myRow] = realloc (c-> nodeConnectivity [myRow],sizeof(int) * c-> allocated[myRow]);
+    HXT_CHECK( hxtRealloc(&c->nodeConnectivity[myRow], sizeof(int) * c->allocated[myRow]) );
   }
   for (int i=0;i<c->degree[myRow];i++){
-    if (c-> nodeConnectivity [myRow][i] == myCol)return 0;
+    if (c-> nodeConnectivity [myRow][i] == myCol) return HXT_STATUS_OK;
   }
   c-> nodeConnectivity [myRow][c->degree[myRow]] = myCol;
   c->degree[myRow]++;
+  return HXT_STATUS_OK;
 }
 
 
-static void reverseCuthillMckee(HXTLinearSystemLU *system, int *ordering)
+static HXTStatus reverseCuthillMckee(HXTLinearSystemLU *system, int *ordering)
 {
 #ifdef CONMAX
-  int *nodeConnectivity = malloc(sizeof(int)*system->nNodes*CONMAX);
+  int *nodeConnectivity;
+  HXT_CHECK( hxtMalloc(&nodeConnectivity, sizeof(int)*system->nNodes*CONMAX) );
   for (int i = 0; i < system->nNodes*CONMAX; ++i) {
     nodeConnectivity[i] = -1;
   }
 #else
   struct HXTConnectivity myConnectivity;
-  mallocConnectivity (&myConnectivity,system->nNodes,9); // 7 is the average connectivity of a triangular mesh, we put a llitle more
+  HXT_CHECK( allocConnectivity (&myConnectivity,system->nNodes,9) ); // 7 is the average connectivity of a triangular mesh, we put a llitle more
 #endif
 
   for (int i = 0; i < system->nElements; ++i) {
@@ -105,17 +109,19 @@ static void reverseCuthillMckee(HXTLinearSystemLU *system, int *ordering)
       for (int l = 0; l < system->nNodesByElement; ++l){
         if (k == l) continue;
 #ifdef CONMAX
-        connectivityInsert(nodeConnectivity, el[k], el[l]);
-        connectivityInsert(nodeConnectivity, el[l], el[k]);
+        HXT_CHECK( connectivityInsert(nodeConnectivity, el[k], el[l]) );
+        HXT_CHECK( connectivityInsert(nodeConnectivity, el[l], el[k]) );
 #else
-	addToConnectivity(&myConnectivity,el[k], el[l]);
-	addToConnectivity(&myConnectivity,el[l], el[k]);
+	HXT_CHECK( addToConnectivity(&myConnectivity,el[k], el[l]) );
+	HXT_CHECK( addToConnectivity(&myConnectivity,el[l], el[k]) );
 #endif
       }
     }
   }
 #ifdef CONMAX
-  int *nodeDegree = malloc(sizeof(int)*system->nNodes);
+
+  int *nodeDegree;
+  HXT_CHECK( hxtMalloc(&nodeDegree, sizeof(int)*system->nNodes) );
   for (int i = 0; i < system->nNodes; ++i) {
     nodeDegree[i] = 0;
     for (int j = 0; j < CONMAX; ++j) {
@@ -128,7 +134,8 @@ static void reverseCuthillMckee(HXTLinearSystemLU *system, int *ordering)
   int *nodeDegree = myConnectivity.degree;
 #endif
 
-  int *queue = malloc(sizeof(int)*system->nNodes);
+  int *queue;
+  HXT_CHECK( hxtMalloc(&queue, sizeof(int)*system->nNodes) );
   queue[0] = 0;
   for (int i = 0; i < system->nNodes; ++i){
     ordering[i] = -1;
@@ -172,25 +179,20 @@ static void reverseCuthillMckee(HXTLinearSystemLU *system, int *ordering)
   for (int i = 0; i < system->nNodes; ++i)
     if(ordering[i] >= 0)
       ordering[i] = id-1-ordering[i];
-  free(queue);
+  HXT_CHECK( hxtFree(&queue) );
 
 #ifdef CONMAX
-  free(nodeDegree);
-  free(nodeConnectivity);
+  HXT_CHECK( hxtFree(&nodeDegree) );
+  HXT_CHECK( hxtFree(&nodeConnectivity) );
 #else
-  freeConnectivity (&myConnectivity);
+  HXT_CHECK( freeConnectivity (&myConnectivity) );
 #endif
+  return HXT_STATUS_OK;
 }
 
 
 #define PADDING (SIMD_ALIGN/8)
 
-
-typedef hxtDeclareAligned double alignedDouble;
-#ifndef HAVE_NO_IMMINTRIN_H // FIXME: Gmsh
-#include <immintrin.h>
-#endif
-
 // y[from:to] += a*x[from:to]
 // y and x must be 256-bit aligned
 // memory should be allocated in consequence
@@ -288,7 +290,7 @@ static HXTStatus LUPDecompose(HXTLinearSystemLU *system){
       rowAxpy(-A[j][i],A[i],A[j],i+1,system->rowEnd[i]);
     }
   }
-  return(1);
+  return HXT_STATUS_OK;
 }
 
 static void LUPSolve(HXTLinearSystemLU *system, double *b){
@@ -303,34 +305,36 @@ static void LUPSolve(HXTLinearSystemLU *system, double *b){
     x[i] -= rowReduction(A[i], x, i+1, imin(system->rowEnd[i], N));
 
     if(fabs(A[i][i])<1e-8)
-      printf("pivot is close to be zero! %d\n",i);
+      HXT_WARNING("pivot is close to be zero! %d\n",i);
     x[i] = x[i]/A[i][i];
   }
 }
 
 HXTStatus hxtLinearSystemLUCreate(HXTLinearSystemLU **pSystem, int nElements, int nNodesByElement, int nFields, uint32_t *elements)
 {
-  HXTLinearSystemLU *system = malloc(sizeof(HXTLinearSystemLU));
+  HXTLinearSystemLU *system;
+  HXT_CHECK( hxtMalloc(&system, sizeof(HXTLinearSystemLU)) );
   *pSystem = system;
   system->nFields = nFields;
   system->nNodesByElement = nNodesByElement;
   system->nElements = nElements;
   system->elements = elements;
-  int nNodes = 0;
+  uint32_t nNodes = 0;
   for (int i = 0; i < nElements*nNodesByElement; ++i)
     if(elements[i]+1 > nNodes)
       nNodes = elements[i]+1;
   system->nNodes = nNodes;
   system->n = nNodes *nFields;
-  system->nodeMap = malloc(sizeof(int)*nNodes);
-  reverseCuthillMckee(system, system->nodeMap);
+  HXT_CHECK( hxtMalloc(&system->nodeMap, sizeof(int)*nNodes) );
+  HXT_CHECK( reverseCuthillMckee(system, system->nodeMap) );
   int nUsedNodes = 0;
-  for (int i = 0; i < nNodes; ++i)
+  for (uint32_t i = 0; i < nNodes; ++i)
     if (system->nodeMap[i] >= 0)
       nUsedNodes ++;
   system->n = nUsedNodes*system->nFields;
-  int *nodeRowStart = malloc(sizeof(int)*nUsedNodes);
-  int *nodeRowEnd = malloc(sizeof(int)*nUsedNodes);
+  int *nodeRowStart, *nodeRowEnd;
+  HXT_CHECK( hxtMalloc(&nodeRowStart, sizeof(int)*nUsedNodes) );
+  HXT_CHECK( hxtMalloc(&nodeRowEnd, sizeof(int)*nUsedNodes) );
   for (int i = 0; i < nUsedNodes; ++i) {
     nodeRowEnd[i] = 0;
     nodeRowStart[i] = nUsedNodes;
@@ -350,9 +354,9 @@ HXTStatus hxtLinearSystemLUCreate(HXTLinearSystemLU **pSystem, int nElements, in
     }
   }
   int totalSize = 0;
-  system->rowStart = malloc(sizeof(int)*system->n);
-  system->rowEnd = malloc(sizeof(int)*system->n);
-  system->rowLuEnd = malloc(sizeof(int)*system->n);
+  HXT_CHECK( hxtMalloc(&system->rowStart, sizeof(int)*system->n) );
+  HXT_CHECK( hxtMalloc(&system->rowEnd, sizeof(int)*system->n) );
+  HXT_CHECK( hxtMalloc(&system->rowLuEnd, sizeof(int)*system->n) );
   for (int i = 0; i < nUsedNodes; ++i) {
     for (int j = 0; j < nFields; ++j) {
       int k = i*nFields +j;
@@ -372,11 +376,12 @@ HXTStatus hxtLinearSystemLUCreate(HXTLinearSystemLU **pSystem, int nElements, in
     int paddedStart = (start+PADDING-1)&~(PADDING-1);
     totalSize += system->rowEnd[i]-system->rowStart[i]+(paddedStart-start);
   }
-  free(nodeRowStart);
-  free(nodeRowEnd);
-  //system->M = _mm_malloc(sizeof(double)*totalSize, PADDING*8);
-  system->M = malloc(sizeof(double)*totalSize); // FIXME Gmsh
-  system->rows = malloc(sizeof(double*)*system->n);
+  HXT_CHECK( hxtFree(&nodeRowStart) );
+  HXT_CHECK( hxtFree(&nodeRowEnd) );
+
+  HXT_CHECK( hxtAlignedMalloc(&system->M, sizeof(double)*totalSize) );
+
+  HXT_CHECK( hxtMalloc(&system->rows, sizeof(double)*system->n) );
   for (int i = 0; i < totalSize; ++i)
     system->M[i] = 0.0;
 
@@ -388,8 +393,8 @@ HXTStatus hxtLinearSystemLUCreate(HXTLinearSystemLU **pSystem, int nElements, in
     totalSize += system->rowEnd[i]-system->rowStart[i]+(paddedStart-start);
     system->rows[i] = system->M + paddedStart;
   }
-  //system->x = _mm_malloc(sizeof(double)*system->n, PADDING*8);
-  system->x = malloc(sizeof(double)*system->n); // FIXME Gmsh
+
+  HXT_CHECK( hxtAlignedMalloc(&system->x, sizeof(double)*system->n) );
   return HXT_STATUS_OK;
 }
 
@@ -498,7 +503,7 @@ HXTStatus hxtLinearSystemLUAddRhsEntry(HXTLinearSystemLU *system, double *rhs, i
 
 HXTStatus hxtLinearSystemLUSolve(HXTLinearSystemLU *system, double *rhs, double *solution){
   if(system->flaglu==0){
-    LUPDecompose(system);
+    HXT_CHECK( LUPDecompose(system) );
     system->flaglu=1;
   }
 
@@ -514,6 +519,9 @@ HXTStatus hxtLinearSystemLUSolve(HXTLinearSystemLU *system, double *rhs, double
 
 HXTStatus hxtLinearSystemLUHasConverged(HXTLinearSystemLU *lsys, int *converged)
 {
+  // Fixme: is this really implemented correctly ? XD
+  HXT_UNUSED(lsys); // unused argument
+
   *converged = 1;
   return HXT_STATUS_OK;
 }
@@ -523,14 +531,14 @@ HXTStatus hxtLinearSystemLUDelete(HXTLinearSystemLU **pSystem)
   HXTLinearSystemLU *system = *pSystem;
   if (system == NULL)
     return HXT_STATUS_OK;
-  free(system->x);
-  free(system->M);
-  free(system->rows);
-  free(system->rowStart);
-  free(system->rowEnd);
-  free(system->rowLuEnd);
-  free(system->nodeMap);
-  free(system);
+  HXT_CHECK( hxtAlignedFree(&system->x) );
+  HXT_CHECK( hxtAlignedFree(&system->M) );
+  HXT_CHECK( hxtFree(&system->rows) );
+  HXT_CHECK( hxtFree(&system->rowStart) );
+  HXT_CHECK( hxtFree(&system->rowEnd) );
+  HXT_CHECK( hxtFree(&system->rowLuEnd) );
+  HXT_CHECK( hxtFree(&system->nodeMap) );
+  HXT_CHECK( hxtFree(&system) );
   *pSystem = NULL;
   return HXT_STATUS_OK;
 }
diff --git a/contrib/hxt/hxt_linear_system_lu.h b/contrib/hxt/reparam/src/hxt_linear_system_lu.h
similarity index 98%
rename from contrib/hxt/hxt_linear_system_lu.h
rename to contrib/hxt/reparam/src/hxt_linear_system_lu.h
index 430060363a..01f1b0f62f 100644
--- a/contrib/hxt/hxt_linear_system_lu.h
+++ b/contrib/hxt/reparam/src/hxt_linear_system_lu.h
@@ -1,7 +1,8 @@
 #ifndef HEXTREME_LINEAR_SYSTEM_LU_H
 #define HEXTREME_LINEAR_SYSTEM_LU_H
+
+#include "hxt_message.h"
 #include <stdint.h>
-#include "hxt_api.h"
 
 #ifndef HEXTREME_LINEAR_SYSTEM_H // to avoid illegal (in C) redefinition of typedef
 typedef struct HXTLinearSystemLUStruct HXTLinearSystemLU;
diff --git a/contrib/hxt/hxt_linear_system_petsc.c b/contrib/hxt/reparam/src/hxt_linear_system_petsc.c
similarity index 88%
rename from contrib/hxt/hxt_linear_system_petsc.c
rename to contrib/hxt/reparam/src/hxt_linear_system_petsc.c
index d359fc642b..aa20e3d515 100644
--- a/contrib/hxt/hxt_linear_system_petsc.c
+++ b/contrib/hxt/reparam/src/hxt_linear_system_petsc.c
@@ -33,31 +33,32 @@ typedef struct SparsityChunkStruct {
   struct SparsityChunkStruct *next;
 }SparsityChunk;
 
-static SparsityChunk *sparsityChunkNew(void)
+static HXTStatus sparsityChunkNew(SparsityChunk** new)
 {
-  SparsityChunk *s = malloc(sizeof(SparsityChunk));
+  HXT_CHECK( hxtMalloc(new, sizeof(SparsityChunk)) );
   for (int i = 0; i < CSIZE; ++i)
-    s->n[i] = -1;
-  s->next = NULL;
-  return s;
+    (*new)->n[i] = -1;
+  (*new)->next = NULL;
 }
 
-static void sparsityChunkInsert(SparsityChunk *s, int id)
+static HXTStatus sparsityChunkInsert(SparsityChunk *s, int id)
 {
   for (int i=0; i<CSIZE; ++i) {
     if (s->n[i] == -1) s->n[i] = id;
     if (s->n[i] == id) return;
   }
-  if (s->next == NULL)
-    s->next = sparsityChunkNew();
-  sparsityChunkInsert(s->next, id);
+  if (s->next == NULL) {
+    HXT_CHECK( sparsityChunkNew(&s->next) );
+  }
+  HXT_CHECK( sparsityChunkInsert(s->next, id) );
 }
 
-static void sparsityChunkFree(SparsityChunk *s)
+static HXTStatus sparsityChunkFree(SparsityChunk *s)
 {
-  if (s->next)
-    sparsityChunkFree(s->next);
-  free(s);
+  if (s->next) {
+    HXT_CHECK( hxtFree(s->next) );
+  }
+  HXT_CHECK( hxtFree(&s) );
 }
 
 static HXTStatus assembleIfNeeded(HXTLinearSystemPETSc *system)
@@ -72,9 +73,11 @@ static HXTStatus assembleIfNeeded(HXTLinearSystemPETSc *system)
 
 static HXTStatus linearSystemPreAllocateMatrix(HXTLinearSystemPETSc *system)
 {
-  SparsityChunk **sparsity = malloc(sizeof(SparsityChunk*)*system->nMappedNodes);
-  for (int i = 0; i < system->nMappedNodes; ++i)
-    sparsity[i] = sparsityChunkNew();
+  SparsityChunk **sparsity;
+  HXT_CHECK( hxtMalloc(&sparsity, sizeof(SparsityChunk*)*system->nMappedNodes) );
+  for (int i = 0; i < system->nMappedNodes; ++i){
+    HXT_CHECK( sparsityChunkNew(&sparsity[i]) );
+  }
   for (int i = 0; i < system->nElements; ++i) {
     uint32_t *el = system->elements + system->nNodesByElement * i;
     for (int k = 0; k < system->nNodesByElement; ++k) {
@@ -85,11 +88,12 @@ static HXTStatus linearSystemPreAllocateMatrix(HXTLinearSystemPETSc *system)
         uint32_t nl = system->nodeMap[el[l]];
         if (nl == -1)
           continue;
-        sparsityChunkInsert(sparsity[nk], nl);
+        HXT_CHECK( sparsityChunkInsert(sparsity[nk], nl) );
       }
     }
   }
-  int *nByRow = malloc(sizeof(int) * system->nMappedNodes*system->nFields);
+  int *nByRow;
+  HXT_CHECK( hxtMalloc(&nByRow, sizeof(int) * system->nMappedNodes*system->nFields) );
   for (uint32_t i = 0; i < system->nMappedNodes; ++i){
     int n = 0;
     SparsityChunk *c = sparsity[i];
@@ -100,14 +104,14 @@ static HXTStatus linearSystemPreAllocateMatrix(HXTLinearSystemPETSc *system)
     for (int j = 0; j < CSIZE; ++j)
       if(c->n[j] != -1)
         n++;
-    sparsityChunkFree(sparsity[i]);
+    HXT_CHECK( sparsityChunkFree(sparsity[i]) );
     for (uint32_t j = 0; j < system->nFields; ++j){
       nByRow[i*system->nFields+j] = n*system->nFields;
     }
   }
-  free(sparsity);
+  HXT_CHECK( hxtFree(&sparsity) );
   HXT_PETSC_CHECK(MatSeqAIJSetPreallocation(system->a, 0, nByRow));
-  free(nByRow);
+  HXT_CHECK( hxtFree(&nByRow) );
   return HXT_STATUS_OK;
 }
 
@@ -117,8 +121,9 @@ HXTStatus hxtLinearSystemPETScAddToMatrix(HXTLinearSystemPETSc *system, int el0,
   int nn = system->nNodesByElement;
   uint32_t *e0 = system->elements + el0*nn;
   uint32_t *e1 = system->elements + el1*nn;
-  int *map0 = malloc(sizeof(int)*nn*nf);
-  int *map1 = malloc(sizeof(int)*nn*nf);
+  int *map0, *map1;
+  HXT_CHECK( hxtMalloc(&map0, sizeof(int)*nn*nf) );
+  HXT_CHECK( hxtMalloc(&map1, sizeof(int)*nn*nf) );
   for(int i=0; i<nn; ++i){
     for (int j=0; j<nf; ++j){
       map0[j*nn+i] = system->nodeMap[e0[i]]*nf+j;
@@ -126,8 +131,8 @@ HXTStatus hxtLinearSystemPETScAddToMatrix(HXTLinearSystemPETSc *system, int el0,
     }
   }
   HXT_PETSC_CHECK(MatSetValues(system->a,nn*nf,map0,nn*nf,map1,localMatrix,ADD_VALUES));
-  free(map0);
-  free(map1);
+  HXT_CHECK( hxtFree(&map0) );
+  HXT_CHECK( hxtFree(&map1) );
   system->assemblyNeeded = 1;
   return HXT_STATUS_OK;
 }
@@ -256,7 +261,8 @@ HXTStatus hxtLinearSystemPETScCreate(HXTLinearSystemPETSc **pSystem, int nElemen
   HXT_PETSC_CHECK(PetscOptionsInsertString(NULL, petscOptions));
   HXT_PETSC_CHECK(PetscOptionsPrefixPop(NULL));
   #endif
-  HXTLinearSystemPETSc *system = malloc(sizeof(HXTLinearSystemPETSc));
+  HXTLinearSystemPETSc *system;
+  HXT_CHECK( hxtMalloc(&system, sizeof(HXTLinearSystemPETSc)) );
   *pSystem = system;
   system->nElements = nElements;
   system->nNodesByElement = nNodesByElement;
@@ -268,7 +274,8 @@ HXTStatus hxtLinearSystemPETScCreate(HXTLinearSystemPETSc **pSystem, int nElemen
       nNodes = elements[i]+1;
   }
   system->nNodes = nNodes;
-  uint32_t *nodeMap = malloc((nNodes)*sizeof(uint32_t));
+  uint32_t *nodeMap;
+  HXT_CHECK( hxtMalloc(&nodeMap, sizeof(uint32_t) * nNodes) );
   for (uint32_t i = 0; i < nNodes; ++i) {
     nodeMap[i] = -1;
   }
@@ -308,8 +315,8 @@ HXTStatus hxtLinearSystemPETScDelete(HXTLinearSystemPETSc **pSystem)
   HXT_PETSC_CHECK(KSPDestroy(&system->ksp));
   HXT_PETSC_CHECK(VecDestroy(&system->x));
   HXT_PETSC_CHECK(MatDestroy(&system->a));
-  free(system->nodeMap);
-  free(system);
+  HXT_CHECK( hxtFree(&system->nodeMap) );
+  HXT_CHECK( hxtFree(&system) );
   *pSystem = NULL;
   return HXT_STATUS_OK;
 }
diff --git a/contrib/hxt/hxt_linear_system_petsc.h b/contrib/hxt/reparam/src/hxt_linear_system_petsc.h
similarity index 98%
rename from contrib/hxt/hxt_linear_system_petsc.h
rename to contrib/hxt/reparam/src/hxt_linear_system_petsc.h
index 416132b986..4b9cf41f71 100644
--- a/contrib/hxt/hxt_linear_system_petsc.h
+++ b/contrib/hxt/reparam/src/hxt_linear_system_petsc.h
@@ -1,7 +1,8 @@
 #ifndef HEXTREME_LINEAR_SYSTEM_PETSC_H
 #define HEXTREME_LINEAR_SYSTEM_PETSC_H
+
+#include "hxt_message.h"
 #include <stdint.h>
-#include "hxt_api.h"
 #include <petscmat.h>
 
 typedef struct HXTLinearSystemPETScStruct HXTLinearSystemPETSc;
diff --git a/contrib/hxt/hxt_mean_values.c b/contrib/hxt/reparam/src/hxt_mean_values.c
similarity index 99%
rename from contrib/hxt/hxt_mean_values.c
rename to contrib/hxt/reparam/src/hxt_mean_values.c
index cea68540c5..bc7a24fee4 100644
--- a/contrib/hxt/hxt_mean_values.c
+++ b/contrib/hxt/reparam/src/hxt_mean_values.c
@@ -1,7 +1,13 @@
 #include "hxt_mean_values.h"
 #include "hxt_edge.h"
 #include "hxt_linear_system.h"
+#include "hxt_tools.h"
+
+
 #include <math.h>
+#ifndef M_PI
+  #define M_PI 3.14159265358979323846264338327950
+#endif // !M_PI
 
 
 
@@ -69,8 +75,6 @@ HXTStatus hxtMeanValuesCreate(HXTEdges *edges, HXTMeanValues **meanValues)
 }
 
 
-HXTStatus hxtMeanValuesDelete(HXTMeanValues **meanValues);
-
 HXTStatus hxtMeanValuesCompute(HXTMeanValues *meanValues){
 
   HXTEdges *edges = meanValues->initialEdges;
@@ -370,6 +374,7 @@ HXTStatus hxtMeanValuesGetData(HXTMeanValues *mv, uint64_t **global,uint32_t **g
 }
 
 
+#ifdef HXT_CORE_FILEIO
 HXTStatus hxtMeanValuesWrite(HXTMeanValues *meanValues, const char* filename)
 {
 
@@ -428,3 +433,5 @@ HXTStatus hxtMeanValuesWriteParamMesh(HXTMeanValues *meanValues,const char* file
 
   return HXT_STATUS_OK;
 }
+
+#endif
diff --git a/contrib/hxt/hxt_non_linear_solver.c b/contrib/hxt/reparam/src/hxt_non_linear_solver.c
similarity index 99%
rename from contrib/hxt/hxt_non_linear_solver.c
rename to contrib/hxt/reparam/src/hxt_non_linear_solver.c
index cfaac46f28..ac15117d3f 100644
--- a/contrib/hxt/hxt_non_linear_solver.c
+++ b/contrib/hxt/reparam/src/hxt_non_linear_solver.c
@@ -1,5 +1,6 @@
 #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;
@@ -16,7 +17,7 @@ HXTStatus hxtNewtonRaphson(HXTLinearSystem *nrSys, double *solution, int size, i
       nrNorm += delta[ie]*delta[ie];
     }
     nrNorm = sqrt(nrNorm);
-    printf("__NR iter %i norm %g\n",n,nrNorm);
+    HXT_INFO("__NR iter %i norm %g\n",n,nrNorm);
     if(nrNorm<tol)
       break;
   }
diff --git a/contrib/hxt/hxt_non_linear_solver.h b/contrib/hxt/reparam/src/hxt_non_linear_solver.h
similarity index 98%
rename from contrib/hxt/hxt_non_linear_solver.h
rename to contrib/hxt/reparam/src/hxt_non_linear_solver.h
index 28054ec5e3..3be8fe11a0 100644
--- a/contrib/hxt/hxt_non_linear_solver.h
+++ b/contrib/hxt/reparam/src/hxt_non_linear_solver.h
@@ -2,7 +2,6 @@
 #define HXT_NON_LINEAR_SOLVER_H
 
 #include "hxt_linear_system.h"
-#include "hxt_api.h"
 
 typedef HXTStatus HXTNonLinearSolverCallbackF(void *data, const double *solution, HXTLinearSystem *sys, double *f);
 typedef HXTStatus HXTNonLinearSolverCallbackDF(void *data, const double *solution, HXTLinearSystem *sys);
diff --git a/contrib/hxt/sizeField/CMakeLists.txt b/contrib/hxt/sizeField/CMakeLists.txt
new file mode 100644
index 0000000000..f3b743ea50
--- /dev/null
+++ b/contrib/hxt/sizeField/CMakeLists.txt
@@ -0,0 +1,15 @@
+# this project is a little bit special, as it needs to be part of GMSH build tree
+
+if(NOT HAVE_P4EST)
+	list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
+
+	find_library(P4EST_LIB p4est)
+	find_path(P4EST_INC "p4est.h" PATH_SUFFIXES src)
+	if((NOT P4EST_LIB) OR (NOT P4EST_INC))
+		message(FATAL_ERROR "P4EST library not found")
+	else()
+		message("found P4est library (${P4EST_LIB})")
+	endif()
+endif()
+
+append_gmsh_src(contrib/hxt/hxt_sizeField "hxt_octree.cpp;hxt_octree.h")
diff --git a/contrib/hxt/hxt_octree.cpp b/contrib/hxt/sizeField/hxt_octree.cpp
similarity index 99%
rename from contrib/hxt/hxt_octree.cpp
rename to contrib/hxt/sizeField/hxt_octree.cpp
index 43e03c45a6..c0a8c0ccd8 100644
--- a/contrib/hxt/hxt_octree.cpp
+++ b/contrib/hxt/sizeField/hxt_octree.cpp
@@ -8,9 +8,11 @@
 #define ALPHA 1.40123
 #define BULK_SIZE 7.77;
 
-#ifdef HAVE_P4EST
-
 p4est_connectivity_t *p8est_connectivity_new_cube (double c);
+
+static inline double hxtNorm2V3(double v[3]){
+  return sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
+}
   
 static double hxtOctreeBulkSize(double x, double y, double z){
   return BULK_SIZE;
@@ -1793,9 +1795,8 @@ static void hxtOctreeRTreeCallback(p4est_iter_volume_info_t * info, void *user_d
           double *v1 = forestOptions->nodalCurvature + 6*node;
           double *v2 = forestOptions->nodalCurvature + 6*node + 3;
 
-          double k1, k2;
-          hxtNorm2V3(v1, &k1);
-          hxtNorm2V3(v2, &k2);
+          double k1 = hxtNorm2V3(v1);
+          double k2 = hxtNorm2V3(v2);
 
           kappa = fmax(kappa,fmax(k1,k2));
         }
@@ -2274,18 +2275,3 @@ p8est_connectivity_new_cube (double c)
 				      NULL, &num_ett, NULL, NULL,
 				      NULL, &num_ctt, NULL, NULL);
 }
-
-#else // HAVE_P4EST
-
-HXTStatus hxtOctreeSearchOne(HXTForest *forest, double x, double y, double z, double *size) {
-
-  *size = 1.e22;
-  static int count = 0;
-  if (count ++ < 20)
-    return HXT_ERROR_MSG(HXT_STATUS_ERROR,"HXT needs P4EST to compute automatic size fields");
-  return HXT_STATUS_ERROR;
-}
-
-
-  
-#endif // HAVE_P4EST
diff --git a/contrib/hxt/hxt_octree.h b/contrib/hxt/sizeField/hxt_octree.h
similarity index 98%
rename from contrib/hxt/hxt_octree.h
rename to contrib/hxt/sizeField/hxt_octree.h
index 67ba99e4cf..a8db22e9a6 100644
--- a/contrib/hxt/hxt_octree.h
+++ b/contrib/hxt/sizeField/hxt_octree.h
@@ -14,7 +14,6 @@
 
 // P4EST INCLUDES
 
-#ifdef HAVE_P4EST
 #include <p4est_to_p8est.h>
 #include <p8est_bits.h>
 #include <p8est_ghost.h>
@@ -23,7 +22,6 @@
 #include <p8est_iterate.h>
 #include <p8est_extended.h>
 #include <p8est_search.h>
-#endif 
 
 // HXT INCLUDES
 
@@ -53,9 +51,7 @@ typedef struct HXTForest{
 // Donnees disponibles sur chaque quadrant
 typedef struct size_data{
   double size;
-#ifdef HAVE_P4EST
   double ds[P4EST_DIM];
-#endif 
   double d2s; // Laplacien
 
   double h;
diff --git a/contrib/hxt/tetBR/CMakeLists.txt b/contrib/hxt/tetBR/CMakeLists.txt
new file mode 100644
index 0000000000..c7feef927c
--- /dev/null
+++ b/contrib/hxt/tetBR/CMakeLists.txt
@@ -0,0 +1,28 @@
+cmake_minimum_required(VERSION 3.9)
+project(hxt_tetBR CXX)
+
+# options are inherited from hxt_core (see ../core/CMakeList.txt)
+
+option(HXT_TETBR_OBJECT_ONLY "Do not create hxt_tetBR library" OFF)
+
+set(HXT_TETBR_SRC
+	"${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})
+else()
+	add_library(hxt_tetBR ${HXT_TETBR_SRC})
+endif()
+
+add_subdirectory(../core "${CMAKE_CURRENT_BINARY_DIR}/hxt_boundaryRecovery_core")
+add_subdirectory(../predicates "${CMAKE_CURRENT_BINARY_DIR}/predicates")
+
+target_include_directories(hxt_tetBR
+                           PUBLIC include
+                           PRIVATE src)
+target_link_libraries(hxt_tetBR
+	                  PUBLIC hxt_core
+                      PRIVATE hxt_predicates)
+
diff --git a/contrib/hxt/tetBR/include/hxt_boundary_recovery.h b/contrib/hxt/tetBR/include/hxt_boundary_recovery.h
new file mode 100644
index 0000000000..80186326f6
--- /dev/null
+++ b/contrib/hxt/tetBR/include/hxt_boundary_recovery.h
@@ -0,0 +1,16 @@
+#ifndef HXT_BOUNDARY_RECOVERY_H
+#define HXT_BOUNDARY_RECOVERY_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "hxt_mesh.h"
+
+HXTStatus hxt_boundary_recovery(HXTMesh *mesh);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/contrib/hxt/hxt_boundary_recovery.cxx b/contrib/hxt/tetBR/src/hxt_boundary_recovery.cxx
similarity index 91%
rename from contrib/hxt/hxt_boundary_recovery.cxx
rename to contrib/hxt/tetBR/src/hxt_boundary_recovery.cxx
index a6a59021d2..808634e06e 100644
--- a/contrib/hxt/hxt_boundary_recovery.cxx
+++ b/contrib/hxt/tetBR/src/hxt_boundary_recovery.cxx
@@ -1,9 +1,8 @@
-#define __STDC_LIMIT_MACROS // FIXME Gmsh (for UINT_MAX & co in C++ code)
-#include <limits.h>
 extern "C" {
 #include "hxt_mesh.h"
-#include "predicates.h"
+#include "hxt_tools.h"
 #include "hxt_omp.h"
+#include "predicates.h"
 }
 
 #include <assert.h>
@@ -71,26 +70,27 @@ static double orient4d(double*, double *, double *, double *, double *,
 #if !defined(TETLIBRARY)
 #define TETLIBRARY
 #endif
+
+#include <cstdio>
+#include <cstring>
 #include "tetgenBR.h"
 #include "tetgenBR.cxx"
 
-// int _edges [12][2] = {{3,2},{3,0},{1,0},{1,2},{2,1},{0,2},{0,3},{2,0},{1,3},{2,3},{3,1},{0,1}};
 
-// int computeTetGenVersion (const int iface1, uint32_t *v1,
-//         uint32_t *v2){
 
-//   uint32_t i1 = v1[_edges[iface1][0]];
-//   uint32_t i2 = v1[_edges[iface1][1]];
-//   for (int i=0;i<12;i++){
-//     if (i2 == v2[_edges[i][0]] &&
-//   i1 == v2[_edges[i][1]]) return i;
-//   }
-//   printf("oulalalala\n");
-//   return -1;
+/* just a function such that:
+ * if hashLess(a,b)==true
+ * then hashLess(b,a)==false
+ *
+ * BUT hashLess(a,b)==true and hashLess(b,c)==true
+ * doesn't imply that hashLess(a,c)==true
+ * and inversely if you replace true with false (no transitivity) */
+static inline uint64_t hashLess(uint64_t a, uint64_t b) {
+  return ((a^b)&1)^(a<b);
+}
 
-// }
 
-static inline int computeTetGenVersion2(uint32_t v1, uint32_t* v2Choices, const int iface2){
+static inline int computeTetGenVersion(uint32_t v1, uint32_t* v2Choices, const int iface2){
   int i;
   for (i=0; i<3; i++) {
       if(v1==v2Choices[i]){
@@ -119,10 +119,10 @@ int tetgenmesh::reconstructmesh(void *p){
   initializepools();
 
   //  printf("we have %u vertices\n", mesh->vertices.num);
-
+  
   {
     point pointloop;
-    REAL x, y, z;
+    REAL x, y, z;    
     // Read the points.
     for (uint32_t i = 0; i < mesh->vertices.num; i++) {
       makepoint(&pointloop, UNUSEDVERTEX);
@@ -162,12 +162,12 @@ int tetgenmesh::reconstructmesh(void *p){
   }
 
   point *idx2verlist;
-
+  
   // Create a map from indices to vertices.
   //  printf("we create a map from indices to vertices\n");
   makeindex2pointmap(idx2verlist);
 
-
+  
   {
     hullsize = 0;
 
@@ -208,17 +208,26 @@ int tetgenmesh::reconstructmesh(void *p){
       for (tf1.ver=0; tf1.ver<4; tf1.ver++){
         uint64_t neigh = mesh->tetrahedra.neigh[4*i + tf1.ver];
         uint64_t n = neigh/4;
-        int iface2 = neigh%4;
 
-        triface tf2 = ts[n];
-
-        // the face of the neighbor tetrahedra that is the same
-        uint32_t face2[3] = {mesh->tetrahedra.node[4*n+((iface2+1)&3)],
-                             mesh->tetrahedra.node[4*n+((iface2&2)^3)],
-                             mesh->tetrahedra.node[4*n+((iface2+3)&2)]};
-
-        tf2.ver = computeTetGenVersion2(mesh->tetrahedra.node[4*i+((tf1.ver+1)&3)], face2, iface2);
-        bond(tf1,tf2);
+        /* we shouldn't compute bond on both side of a facet, so we must
+         * give a priority to one side.
+         * simply using if(i<n) would produce load imbalance
+         * as the first thread, which takes care of the first tet
+         * would have much more work to do. Therefore, we use the
+         * hashLess function */
+        if(hashLess(i, n)) {
+          int iface2 = neigh%4;
+          
+          triface tf2 = ts[n];
+
+          // the face of the neighbor tetrahedra that is the same
+          uint32_t face2[3] = {mesh->tetrahedra.node[4*n+((iface2+1)&3)],
+                               mesh->tetrahedra.node[4*n+((iface2&2)^3)],
+                               mesh->tetrahedra.node[4*n+((iface2+3)&2)]};
+
+          tf2.ver = computeTetGenVersion(mesh->tetrahedra.node[4*i+((tf1.ver+1)&3)], face2, iface2);
+          bond(tf1,tf2);
+        }
       }
     }
   }
@@ -232,8 +241,8 @@ int tetgenmesh::reconstructmesh(void *p){
       tetrahedron tptr = encode(tetloop);
       for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
         // Create the point-to-tet map.
-        setpoint2tet((point) (tetloop.tet[4 + tetloop.ver]), tptr);
-
+        setpoint2tet((point) (tetloop.tet[4 + tetloop.ver]), tptr); 
+  
         // Clean the temporary used space.
         tetloop.tet[8 + tetloop.ver] = NULL;
       }
@@ -246,7 +255,7 @@ int tetgenmesh::reconstructmesh(void *p){
     face newseg;
     point p[4];
     int idx;
-
+    
     for (uint64_t i=0;i<mesh->triangles.num;i++){
       for (uint64_t j = 0; j < 3; j++) {
         p[j] = idx2verlist[mesh->triangles.node[3*i+j]];
@@ -254,7 +263,7 @@ int tetgenmesh::reconstructmesh(void *p){
           setpointtype(p[j], FACETVERTEX);
         }
       }
-
+      
       // Create an initial triangulation.
       makeshellface(subfaces, &newsh);
       setshvertices(newsh, p[0], p[1], p[2]);
@@ -272,17 +281,17 @@ int tetgenmesh::reconstructmesh(void *p){
     } // i
 
     unifysegments();
-
-
+    
+    
     face* shperverlist;
     int* idx2shlist;
     face searchsh, neighsh;
     face segloop, checkseg;
     point checkpt;
-
+    
     // Construct a map from points to subfaces.
     makepoint2submap(subfaces, idx2shlist, shperverlist);
-
+    
     // Process the set of PSC edges.
     // Remeber that all segments have default marker '-1'.
     //    int COUNTER = 0;
@@ -298,7 +307,7 @@ int tetgenmesh::reconstructmesh(void *p){
           // This is a potential problem in surface mesh.
           continue; // Skip this edge.
         }
-
+        
         // Find a face contains the edge p[0], p[1].
         newseg.sh = NULL;
         searchsh.sh = NULL;
@@ -362,7 +371,7 @@ int tetgenmesh::reconstructmesh(void *p){
         }
         setshellmark(newseg, mesh->lines.colors[i]);
       } // i
-
+      
       delete [] shperverlist;
       delete [] idx2shlist;
       insegments = subsegs->items;
@@ -371,7 +380,7 @@ int tetgenmesh::reconstructmesh(void *p){
 
   delete [] idx2verlist;
   clock_t t = clock();
-  recoverboundary(t);
+  recoverboundary(t);  
   //  printf("Carve Holes\n");
   //  carveholes();
   if (subvertstack->objects > 0l) {
@@ -391,7 +400,7 @@ int tetgenmesh::reconstructmesh(void *p){
     // Write mesh into to HXT.
     point p[4];
     std::set<int> /*l_faces, */l_edges;
-
+    
     if (points->items > mesh->vertices.num) {
       mesh->vertices.num = points->items;
       if(mesh->vertices.num > mesh->vertices.size) {
@@ -400,7 +409,7 @@ int tetgenmesh::reconstructmesh(void *p){
                                     4*mesh->vertices.num*sizeof( double )) );
         mesh->vertices.size = mesh->vertices.num;
       }
-
+            
       face parentseg, parentsh, spinsh;
       point pointloop;
       // Create newly added mesh vertices.
@@ -450,10 +459,10 @@ int tetgenmesh::reconstructmesh(void *p){
       if (reconstructingTriangularMeshIsRequired) {
         // restore 2D mesh ...
         HXT_CHECK( hxtAlignedFree(&(mesh->triangles.node)));
-        HXT_CHECK( hxtAlignedFree(&(mesh->triangles.colors)));
+        HXT_CHECK( hxtAlignedFree(&(mesh->triangles.colors)));      
         HXT_INFO("deleting %u triangles",mesh->triangles.num);
         mesh->triangles.num = 0; // firstindex; // in->firstnumber;
-        {
+        {    
           face subloop;
           subloop.shver = 0;
           subfaces->traversalinit();
@@ -494,10 +503,10 @@ int tetgenmesh::reconstructmesh(void *p){
         }
       }
     }
-
+    
     // TODO: maybe fill a vector with triface and use that to convert in parallel ?
     int elementnumber = 0; // firstindex; // in->firstnumber;
-    {
+    {    
       // number tets
       triface tetloop;
       tetrahedrons->traversalinit();
@@ -511,10 +520,10 @@ int tetgenmesh::reconstructmesh(void *p){
 
     if(elementnumber!=tetrahedrons->items)
       return HXT_ERROR_MSG(HXT_STATUS_ERROR, "This can not happen...");
-
+    
     {
       // move data to HXT
-      triface tetloop;
+      triface tetloop;    
       tetrahedrons->traversalinit();
       tetloop.tet = alltetrahedrontraverse();
 
@@ -537,8 +546,8 @@ int tetgenmesh::reconstructmesh(void *p){
 
         mesh->tetrahedra.size = mesh->tetrahedra.num;
       }
-
-
+      
+      
       int counter = 0;
       while (tetloop.tet != (tetrahedron *) NULL) {
         tetloop.ver = 11;
@@ -563,7 +572,7 @@ int tetgenmesh::reconstructmesh(void *p){
           else {
             mesh->tetrahedra.node[4*counter+k] = pointmark(p[k]);
             if (mesh->tetrahedra.node[4*counter+k] >= mesh->vertices.num)
-              return HXT_ERROR_MSG(HXT_STATUS_ERROR, "ERROR : index %u out of range (%u)\n",
+              return HXT_ERROR_MSG(HXT_STATUS_ERROR, "ERROR : index %u out of range (%u)\n", 
                                    mesh->tetrahedra.node[4*counter+k], mesh->vertices.num);
           }
 
diff --git a/contrib/hxt/tetgenBR.cxx b/contrib/hxt/tetBR/src/tetgenBR.cxx
similarity index 100%
rename from contrib/hxt/tetgenBR.cxx
rename to contrib/hxt/tetBR/src/tetgenBR.cxx
diff --git a/contrib/hxt/tetgenBR.h b/contrib/hxt/tetBR/src/tetgenBR.h
similarity index 99%
rename from contrib/hxt/tetgenBR.h
rename to contrib/hxt/tetBR/src/tetgenBR.h
index 13b1903719..d47ef862f8 100644
--- a/contrib/hxt/tetgenBR.h
+++ b/contrib/hxt/tetBR/src/tetgenBR.h
@@ -215,7 +215,7 @@ public:
     brio_threshold = 64;
     brio_ratio = 0.125;
     facet_separate_ang_tol = 179.9;
-    facet_overlap_ang_tol = 0.001;
+    facet_overlap_ang_tol = 0.01;
     facet_small_ang_tol = 15.0;
     maxvolume = -1.0;
     minratio = 2.0;
diff --git a/contrib/hxt/tetMesh/CMakeLists.txt b/contrib/hxt/tetMesh/CMakeLists.txt
new file mode 100644
index 0000000000..0d813fb47a
--- /dev/null
+++ b/contrib/hxt/tetMesh/CMakeLists.txt
@@ -0,0 +1,59 @@
+cmake_minimum_required(VERSION 3.9)
+project(hxt_tetMesh C)
+
+# options are inherited from hxt_core (see ../core/CMakeList.txt)
+
+option(HXT_TETMESH_OBJECT_ONLY "Do not create hxt_tetMesh library" OFF)
+
+set(HXT_TETMESH_SRC
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/HXTSPR.c"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_tetFlag.c"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_tetMesh.c"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_tetOpti.c"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_tetSync.c"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_tetColor.c"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_tetUtils.c"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_vertices.c"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_smoothing.c"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_tetRefine.c"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_tetRepair.c"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_tetQuality.c"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/hxt_edgeRemoval.c"
+    "${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_tetMesh.h"
+   )
+
+if(HXT_TETMESH_OBJECT_ONLY)
+    add_library(hxt_tetMesh OBJECT ${HXT_TETMESH_SRC})
+else()
+    add_library(hxt_tetMesh ${HXT_TETMESH_SRC})
+endif()
+
+add_subdirectory(../core "${CMAKE_CURRENT_BINARY_DIR}/core")
+add_subdirectory(../predicates "${CMAKE_CURRENT_BINARY_DIR}/predicates")
+
+target_include_directories(hxt_tetMesh
+                           PUBLIC include
+                           PRIVATE src)
+target_link_libraries(hxt_tetMesh
+                      PUBLIC hxt_core
+                      PRIVATE hxt_predicates)
+target_compile_features(hxt_tetMesh PRIVATE c_std_99)
+
diff --git a/contrib/hxt/hxt_tetMesh.h b/contrib/hxt/tetMesh/include/hxt_tetMesh.h
similarity index 93%
rename from contrib/hxt/hxt_tetMesh.h
rename to contrib/hxt/tetMesh/include/hxt_tetMesh.h
index 6c6311e7c1..018182e0d8 100644
--- a/contrib/hxt/hxt_tetMesh.h
+++ b/contrib/hxt/tetMesh/include/hxt_tetMesh.h
@@ -1,5 +1,13 @@
-#ifndef _HXT_TETMESH_
-#define _HXT_TETMESH_
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
+#ifndef HXT_TETMESH_H
+#define HXT_TETMESH_H
 
 #include "hxt_mesh.h"
 
@@ -50,7 +58,7 @@ typedef struct {
   void* meshSizeData;  /* user pointer to give to meshSizeFun */
 
   /* function to recover missing features in a mesh */
-  HXTStatus (*recoveryFun)(HXTMesh* mesh, void* userData);
+  HXTStatus (*recoveryFun)(HXTMesh* mesh, void* recoveryData);
   void* recoveryData;  /* user pointer to give to recoveryFun */
 } HXTTetMeshOptions;
 
diff --git a/contrib/hxt/HXTSPR.c b/contrib/hxt/tetMesh/src/HXTSPR.c
similarity index 91%
rename from contrib/hxt/HXTSPR.c
rename to contrib/hxt/tetMesh/src/HXTSPR.c
index 37232bc956..25073f1f34 100644
--- a/contrib/hxt/HXTSPR.c
+++ b/contrib/hxt/tetMesh/src/HXTSPR.c
@@ -1,23 +1,13 @@
-/*  This file is part of HXTSPR.                                            *
-                                                                            *
-    HXTSPR is free software: you can redistribute it and/or modify          *
-    it under the terms of the GNU General Public License as published by    *
-    the Free Software Foundation, either version 3 of the License, or       *
-    (at your option) any later version.                                     *
-                                                                            *
-    HXTSPR is distributed in the hope that it will be useful,               *
-    but WITHOUT ANY WARRANTY; without even the implied warranty of          *
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
-    GNU General Public License for more details.                            *
-                                                                            *
-    You should have received a copy of the GNU General Public License       *
-    along with HXTSPR.  If not, see <http://www.gnu.org/licenses/>.         *
-                                                                            *
-    See the COPYING file for the GNU General Public License .               *
-                                                                            *
-Author: Célestin Marot (celestin.marot@uclouvain.be)                        */
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
 
 #include "HXTSPR.h"
+#include <math.h>
 #include "hxt_tetFlag.h"
 #include "predicates.h"
 
@@ -1141,8 +1131,8 @@ static void add_knownPositive_quality_map(SPRCavity* SPR,
                                           unsigned v3,
                                           double qual)
 {
-  int orientation = get_orient3d(SPR, v0, v1, v2, v3);
 #ifndef NDEBUG
+  int orientation = get_orient3d(SPR, v0, v1, v2, v3);
   if(orientation >= 0.0){
     HXT_WARNING("a tetrahedron has a negative volume but a quality of %f", qual);
   }
@@ -1174,11 +1164,11 @@ static int tetOutOfPartition(HXTVertex* vertices,
  *            growingCav->worstQuality is the quality of that tet
  *            growingCav->meshAdjacencies[] are the adjacencies of that tet */
 static inline HXTStatus SPROpti_init(SPRGrowingCavity* growingCav,
-                                     HXTSPRData* data,
+                                     ThreadLocal* local,
                                      uint64_t badTet)
 {
   SPRCavity* SPR = &growingCav->cavity;
-  growingCav->worstQuality = data->quality->values[badTet];
+  growingCav->worstQuality = local->quality->values[badTet];
 
   // initialize the SPR structure maps and arrays
   SPR_clear_maps(SPR);
@@ -1188,21 +1178,21 @@ static inline HXTStatus SPROpti_init(SPRGrowingCavity* growingCav,
   SPR->triangles.num = 0; // add_face() (in second for loop) already increments num
   SPR->tetrahedra.num = 1;
   SPR->tetrahedra.array[0] = (SPRTet) {{0,1,2,3}};
-  SPR->tetrahedra.quality = data->quality->values[badTet];
-  SPR->quality.function = data->quality->function;
-  SPR->quality.userData = data->quality->userData;
+  SPR->tetrahedra.quality = local->quality->values[badTet];
+  SPR->quality.function = local->quality->function;
+  SPR->quality.userData = local->quality->userData;
   SPR->num_search_nodes = 0;
-  SPR->max_search_nodes = data->maxSearchNodes;
+  SPR->max_search_nodes = local->SPR.maxSearchNodes;
 
-  HXTMesh* mesh = data->toSync->mesh;
-  HXTPartition* partition = data->partition;
+  HXTMesh* mesh = local->toSync->mesh;
+  HXTPartition* partition = &local->partition;
   HXTVertex* vertices = (HXTVertex*) mesh->vertices.coord;
 
   // maybe this is unnecessary... better check anyway
   if(tetOutOfPartition(vertices, partition, &mesh->tetrahedra.node[4*badTet]))
     return HXT_STATUS_CONFLICT;
 
-  HXTDeleted* deleted = data->deleted;
+  HXTDeleted* deleted = &local->deleted;
   HXT_CHECK( askForDeleted(deleted, 1) );
   setDeletedFlag(mesh, badTet);
   deleted->array[deleted->num++] = badTet;
@@ -1221,7 +1211,7 @@ static inline HXTStatus SPROpti_init(SPRGrowingCavity* growingCav,
     };
   }
 
-  add_knownPositive_quality_map(SPR, 0, 1, 2, 3, data->quality->values[badTet]);
+  add_knownPositive_quality_map(SPR, 0, 1, 2, 3, local->quality->values[badTet]);
 
   // adding faces and linked stuffs
   for(int i=0; i<4; i++) {
@@ -1240,8 +1230,8 @@ static inline HXTStatus SPROpti_init(SPRGrowingCavity* growingCav,
 
 
 static inline HXTStatus find_best_point(SPRGrowingCavity* growingCav,
-                                       HXTSPRData* data,
-                                       int* bestPoint) {
+                                        ThreadLocal* local,
+                                        int* bestPoint) {
   /* A point is good if it is very connected to the cavity !
    * (connection <==> a tet containing the point having a face on the cavity)
    * If multiple points have the same number of connections the quality of
@@ -1254,7 +1244,7 @@ static inline HXTStatus find_best_point(SPRGrowingCavity* growingCav,
    * opposite_point[] array, If it is present, we increment numConnected.
    */
   SPRCavity* SPR = &growingCav->cavity;
-  HXTMesh* mesh = data->toSync->mesh;
+  HXTMesh* mesh = local->toSync->mesh;
   uint64_t* adjacencies = growingCav->meshAdjacencies;
 
   uint32_t opposite_point[SPR_MAX_TRIANGLES];
@@ -1308,6 +1298,9 @@ static inline HXTStatus find_best_point(SPRGrowingCavity* growingCav,
     }
   }
 
+  if(mostNumConnected==0) // cavity is completely constrained
+    return HXT_STATUS_INTERNAL;
+
   /* if there is equality, we must compute the sum of qualities
    * for each point with mostNumConnected connection   */
   if(equality) {
@@ -1320,9 +1313,9 @@ static inline HXTStatus find_best_point(SPRGrowingCavity* growingCav,
         double score = 0.0;
 
         for(int t=0; t<SPR->triangles.num; t++) {
-          if(adjacencies[t]==HXT_NO_ADJACENT || mesh->tetrahedra.node[adjacencies[t]]!=node)
+          if(adjacencies[t]==HXT_NO_ADJACENT || mesh->tetrahedra.node[adjacencies[t]]!=node || getFacetConstraint(mesh, adjacencies[t]/4, adjacencies[t]%4))
             continue;
-          score += data->quality->values[adjacencies[t]/4];
+          score -= local->quality->values[adjacencies[t]/4];
         }
 
         if(score > bestScore) {
@@ -1382,13 +1375,13 @@ static inline int needNewSPREdge(HXTMesh* mesh, uint64_t meshTet, int in_facet,
 
 /* attach the best point (see find_best_point()) to the cavity */
 static inline HXTStatus attach_best_point(SPRGrowingCavity* growingCav,
-                                          HXTSPRData* data)
+                                          ThreadLocal* local)
 {
   SPRCavity* SPR = &growingCav->cavity;
-  HXTMesh* mesh = data->toSync->mesh;
+  HXTMesh* mesh = local->toSync->mesh;
 
   int newNode;
-  HXT_CHECK( find_best_point(growingCav, data, &newNode) );
+  HXT_CHECK( find_best_point(growingCav, local, &newNode) );
 
   // we can now add mostConnectPoint !! :-)
   double* coord = &mesh->vertices.coord[4*newNode];
@@ -1404,10 +1397,10 @@ static inline HXTStatus attach_best_point(SPRGrowingCavity* growingCav,
   uint64_t* adjacencies = growingCav->meshAdjacencies;
 
   /* we delete tetrahedra that contain the added point. */
-  HXTPartition* partition = data->partition;
+  HXTPartition* partition = &local->partition;
   HXTVertex* vertices = (HXTVertex*) mesh->vertices.coord;
 
-  HXTDeleted* deleted = data->deleted;
+  HXTDeleted* deleted = &local->deleted;
 
   for(int i=0; i<SPR->triangles.num;) { // notice we don't increment i here
     uint64_t meshTet = adjacencies[i]/4;
@@ -1475,12 +1468,12 @@ static inline HXTStatus attach_best_point(SPRGrowingCavity* growingCav,
     // add the quality of the meshTet to known cavities :-)
     add_knownPositive_quality_map(SPR,
                                   tetV[0], tetV[1], tetV[2], tetV[3],
-                                  data->quality->values[meshTet]);
+                                  local->quality->values[meshTet]);
 
     // update the quality to the worst one...
-    if(data->quality->values[meshTet] < growingCav->worstQuality) {
-      SPR->tetrahedra.quality = data->quality->values[meshTet];
-      growingCav->worstQuality = data->quality->values[meshTet];
+    if(local->quality->values[meshTet] < growingCav->worstQuality) {
+      SPR->tetrahedra.quality = local->quality->values[meshTet];
+      growingCav->worstQuality = local->quality->values[meshTet];
     }
 
     adjacencies[i] = adjacencies[SPR->triangles.num-1];
@@ -1603,26 +1596,34 @@ static HXTStatus fillConstrainedEdgeMap(HXTMesh* mesh, SPRCavity* SPR,
 /* replace the interior of the cavity within the mesh by the triangulation
  * found by hxtSPR() */
 static inline HXTStatus rebuildMesh(SPRGrowingCavity* growingCav,
-                                    HXTSPRData* data,
+                                    ThreadLocal* local,
+#ifdef DEBUG
                                     uint64_t prevNumDeleted,
+#endif
                                     uint64_t badTet)
 {
-  HXTDeleted* deleted = data->deleted;
-  HXTMesh* mesh = data->toSync->mesh;
+  HXTDeleted* deleted = &local->deleted;
+  HXTMesh* mesh = local->toSync->mesh;
   uint16_t color = mesh->tetrahedra.colors[badTet];
-  uint16_t lastCheck = data->dateOfLastCheck;
-  data->dateOfLastCreation = lastCheck;
+  uint16_t lastCheck = local->SPR.dateOfLastCheck;
+  local->SPR.dateOfLastCreation = lastCheck;
 
   SPRCavity* SPR = &growingCav->cavity;
 
+#ifdef DEBUG
+  int adjacencies_to_nowhere = 0;
+  for(uint64_t i=prevNumDeleted; i<deleted->num; i++) {
+    uint64_t oldTet = deleted->array[i];
+    for(int j=0; j<4; j++) {
+      if(mesh->tetrahedra.neigh[4*oldTet + j] == HXT_NO_ADJACENT)
+        adjacencies_to_nowhere++;
+    }
+  }
+#endif
+
   // we integrate the SPR cavity into the mesh
   if((uint64_t) SPR->tetrahedra.num > deleted->num) {
-    HXT_CHECK( createNewDeleted(data->toSync, deleted, SPR->tetrahedra.num) );
-  }
-  else if((uint64_t) SPR->tetrahedra.num < deleted->num - prevNumDeleted) {
-    for(uint64_t i=prevNumDeleted; i<deleted->num - SPR->tetrahedra.num; i++) {
-      data->quality->values[deleted->array[i]] = DBL_MAX;
-    }
+    HXT_CHECK( createNewDeleted(local->toSync, deleted, SPR->tetrahedra.num) );
   }
 
   uint64_t* adjacencies = growingCav->meshAdjacencies;
@@ -1648,9 +1649,9 @@ static inline HXTStatus rebuildMesh(SPRGrowingCavity* growingCav,
     mesh->tetrahedra.flag[meshTet] = 0;
 
     unsigned index = get_compressed_index(v[0], v[1], v[2], v[3]);
-    data->quality->values[meshTet] = SPR->map.qualities[index];
-    data->date->values[meshTet].creation = lastCheck;
-    data->date->values[meshTet].check = lastCheck;
+    local->quality->values[meshTet] = SPR->map.qualities[index];
+    local->date->values[meshTet].creation = lastCheck;
+    local->date->values[meshTet].check = lastCheck;
 
     for(int j=0; j<4; j++) {
       // try to find the face in SPRTriangles
@@ -1659,13 +1660,18 @@ static inline HXTStatus rebuildMesh(SPRGrowingCavity* growingCav,
                                     v[getNode1FromFacet(j)],
                                     v[getNode2FromFacet(j)]);
 
+      remove_face_map(SPR, v[getNode0FromFacet(j)],
+                           v[getNode1FromFacet(j)],
+                           v[getNode2FromFacet(j)]);
+
       if(index==UINT16_MAX) {
         mesh->tetrahedra.neigh[4*meshTet + j] = HXT_NO_ADJACENT;
       }
       else {
         uint64_t adj = adjacencies[index];
 
-        if(adj==HXT_NO_ADJACENT) { // happens for constrained faces
+        if(adj==HXT_NO_ADJACENT) { // happens for constrained faces, or
+                                   // when there are no ghosts
           mesh->tetrahedra.neigh[4*meshTet + j] = HXT_NO_ADJACENT;
           setFacetConstraint(mesh, meshTet, j);
         }
@@ -1698,7 +1704,8 @@ static inline HXTStatus rebuildMesh(SPRGrowingCavity* growingCav,
     return HXT_ERROR_MSG(HXT_STATUS_ERROR, "DEBUG: missing external adjacency");
 #endif
 
-  /* now, all external adjacencies have been found, we just have to find internal adjacencies :p */
+  /* now, all external adjacencies (except HXT_NO_ADJACENT ones obviously)
+   *  have been found, we just have to find internal adjacencies :p */
   for(int i=0; i<SPR->tetrahedra.num; i++) {
     uint64_t meshTet = newTet[i];
 
@@ -1722,8 +1729,10 @@ static inline HXTStatus rebuildMesh(SPRGrowingCavity* growingCav,
                                     SPR->tetrahedra.array[i].node[getNode0FromFacet(j)],
                                     SPR->tetrahedra.array[i].node[getNode2FromFacet(j)],
                                     SPR->tetrahedra.array[i].node[getNode1FromFacet(j)]);
-        uint64_t neighTet = newTet[adj/4];
-        mesh->tetrahedra.neigh[4*meshTet+j] = 4*neighTet + adj%4;
+        if(adj!=UINT16_MAX) {
+          uint64_t neighTet = newTet[adj/4];
+          mesh->tetrahedra.neigh[4*meshTet+j] = 4*neighTet + adj%4;
+        }
       }
     }
   }
@@ -1734,17 +1743,20 @@ static inline HXTStatus rebuildMesh(SPRGrowingCavity* growingCav,
 
     for (int j=0; j<4; ++j)
     {
-      if(mesh->tetrahedra.neigh[4*meshTet+j]>=4*mesh->tetrahedra.num) {
-        return HXT_ERROR_MSG(HXT_STATUS_ERROR, "one of the tetrahedron is missing a neighbor");
+      if(mesh->tetrahedra.neigh[4*meshTet+j]==HXT_NO_ADJACENT) {
+        adjacencies_to_nowhere--;
       }
-    }
-    for (int j=0; j<4; ++j)
-    {
-      if(mesh->tetrahedra.neigh[mesh->tetrahedra.neigh[4*meshTet+j]]!=4*meshTet+j){
+      else if(mesh->tetrahedra.neigh[4*meshTet+j]!=HXT_NO_ADJACENT && mesh->tetrahedra.neigh[4*meshTet+j]/4>=mesh->tetrahedra.num) {
+        return HXT_ERROR_MSG(HXT_STATUS_ERROR, "invalid neighbor");
+      }
+      else if(mesh->tetrahedra.neigh[mesh->tetrahedra.neigh[4*meshTet+j]]!=4*meshTet+j){
         return HXT_ERROR_MSG(HXT_STATUS_ERROR, "one of the tetrahedron is not the neighbor of its neighbor");
       }
     }
   }
+
+  if(adjacencies_to_nowhere!=0)
+    return HXT_ERROR_MSG(HXT_STATUS_ERROR, "there are unrecovered adjacencies");
 #endif
 
   deleted->num -= SPR->tetrahedra.num;
@@ -1757,11 +1769,11 @@ static inline HXTStatus rebuildMesh(SPRGrowingCavity* growingCav,
  * if none of the date are as recent as the last check
  * return 0
  * else, return 1 */
-int verifyDates(HXTSPRData* data, uint64_t prevNumDeleted, uint16_t lastCheck)
+int verifyDates(ThreadLocal* local, uint64_t prevNumDeleted, uint16_t lastCheck)
 {
-  HXTDeleted* deleted = data->deleted;
+  HXTDeleted* deleted = &local->deleted;
   for(uint64_t i=prevNumDeleted; i<deleted->num; i++) {
-    uint16_t creation = data->date->values[deleted->array[i]].creation;
+    uint16_t creation = local->date->values[deleted->array[i]].creation;
     if(creation >= lastCheck)
       return 1;
   }
@@ -1772,18 +1784,18 @@ int verifyDates(HXTSPRData* data, uint64_t prevNumDeleted, uint16_t lastCheck)
 
 /* we checked the growing cavity till the end but it didn't work
  * we mark the date of this failure... */
-HXTStatus setCheckDate(HXTSPRData* data, uint64_t badTet)
+HXTStatus setCheckDate(ThreadLocal* local, uint64_t badTet)
 {
-  data->date->values[badTet].check = data->dateOfLastCreation + 1;
-  data->dateOfLastCheck = data->dateOfLastCreation + 1;
+  local->date->values[badTet].check = local->SPR.dateOfLastCreation + 1;
+  local->SPR.dateOfLastCheck = local->SPR.dateOfLastCreation + 1;
   return HXT_STATUS_OK;
 }
 
 
-static void deleted_reset(HXTSPRData* data, uint64_t prevNumDeleted)
+static void deleted_reset(ThreadLocal* local, uint64_t prevNumDeleted)
 {
-  HXTDeleted* deleted = data->deleted;
-  HXTMesh* mesh = data->toSync->mesh;
+  HXTDeleted* deleted = &local->deleted;
+  HXTMesh* mesh = local->toSync->mesh;
   for(uint64_t i=prevNumDeleted; i<deleted->num; i++) {
     unsetDeletedFlag(mesh, deleted->array[i]);
   }
@@ -1795,25 +1807,24 @@ static void deleted_reset(HXTSPRData* data, uint64_t prevNumDeleted)
 
 
 
-HXTStatus hxtSPR_opti(HXTSPRData* data,
+HXTStatus hxtSPR_opti(ThreadLocal* local,
                       uint64_t badTet)
 {
   SPRGrowingCavity growingCav;  // all the structure on the stack... it should fit ^^
   SPRCavity* SPR = &growingCav.cavity;
-  uint64_t prevNumDeleted = data->deleted->num;
+  uint64_t prevNumDeleted = local->deleted.num;
 
-  uint16_t lastCheck = data->date->values[badTet].check;
+  uint16_t lastCheck = local->date->values[badTet].check;
   int datesOk = 0;
 
-  HXT_CHECK( SPROpti_init(&growingCav, data, badTet) );
-
-  int lastNumPoints = 4;
+  HXT_CHECK( SPROpti_init(&growingCav, local, badTet) );
 
   do {
-    HXTStatus status = attach_best_point(&growingCav, data);
+    // return HXT_STATUS_INTERNAL if the cavity if completely constrained
+    HXTStatus status = attach_best_point(&growingCav, local);
 
-    if(status==HXT_STATUS_CONFLICT) {
-      deleted_reset(data, prevNumDeleted);
+    if(status==HXT_STATUS_CONFLICT || status==HXT_STATUS_INTERNAL) {
+      deleted_reset(local, prevNumDeleted);
       return status;
     }
     else if(status!=HXT_STATUS_OK) {
@@ -1822,7 +1833,7 @@ HXTStatus hxtSPR_opti(HXTSPRData* data,
     }
 
     if(datesOk==0)
-      datesOk = verifyDates(data, prevNumDeleted, lastCheck);
+      datesOk = verifyDates(local, prevNumDeleted, lastCheck);
 
     if(datesOk) {
       /* applying the SPR algorithm, only initializing the necessary minimum */
@@ -1844,8 +1855,8 @@ HXTStatus hxtSPR_opti(HXTSPRData* data,
         }
         else {
           // HXT_WARNING("Maximum nodes of SPR search reached");
-          deleted_reset(data, prevNumDeleted);
-          setCheckDate(data, badTet);
+          deleted_reset(local, prevNumDeleted);
+          setCheckDate(local, badTet);
           return HXT_STATUS_INTERNAL;
         }
       }
@@ -1871,13 +1882,18 @@ HXTStatus hxtSPR_opti(HXTSPRData* data,
 
     if(growingCav.cavity.points.num==SPR_MAX_PTS) {
       // HXT_WARNING("Too much points in SPR cavity");
-      deleted_reset(data, prevNumDeleted);
-      setCheckDate(data, badTet);
+      deleted_reset(local, prevNumDeleted);
+      setCheckDate(local, badTet);
       return HXT_STATUS_INTERNAL;
     }
   } while(1);
 
-  HXT_CHECK( rebuildMesh(&growingCav, data, prevNumDeleted, badTet) );
+  HXT_CHECK( rebuildMesh(&growingCav,
+                         local,
+#ifdef DEBUG
+                         prevNumDeleted,
+#endif
+                         badTet) );
 
   return HXT_STATUS_OK;
 }
diff --git a/contrib/hxt/HXTSPR.h b/contrib/hxt/tetMesh/src/HXTSPR.h
similarity index 79%
rename from contrib/hxt/HXTSPR.h
rename to contrib/hxt/tetMesh/src/HXTSPR.h
index d0daa46ac8..83145102fc 100644
--- a/contrib/hxt/HXTSPR.h
+++ b/contrib/hxt/tetMesh/src/HXTSPR.h
@@ -1,36 +1,20 @@
-/*  This file is part of HXTSPR.                                            *
-                                                                            *
-    HXTSPR is free software: you can redistribute it and/or modify          *
-    it under the terms of the GNU General Public License as published by    *
-    the Free Software Foundation, either version 3 of the License, or       *
-    (at your option) any later version.                                     *
-                                                                            *
-    HXTSPR is distributed in the hope that it will be useful,               *
-    but WITHOUT ANY WARRANTY; without even the implied warranty of          *
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
-    GNU General Public License for more details.                            *
-                                                                            *
-    You should have received a copy of the GNU General Public License       *
-    along with HXTSPR.  If not, see <http://www.gnu.org/licenses/>.         *
-                                                                            *
-    See the COPYING file for the GNU General Public License .               *
-                                                                            *
-Author: Célestin Marot (celestin.marot@uclouvain.be)                        */
-
-
-#ifndef _HXTSPR_
-#define _HXTSPR_
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
+
+#ifndef HXTSPR_H
+#define HXTSPR_H
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-#include "hxt_tetSync.h"
-#include "hxt_tetPartition.h"
-#include "hxt_tetQuality.h"
-#include "hxt_tetOptiDate.h"
-#include "hxt_bbox.h"
-
+#include "hxt_tetOptiUtils.h"
 
 /* /!\ Warning /!\ This version is a modified version of HXTSPR
  *
@@ -214,21 +198,6 @@ typedef struct {
 HXTStatus hxtSPR(SPRCavity* cavity);
 
 
-
-typedef struct {
-  HXTDeleted* deleted;
-  HXTPartition* partition;
-  HXTTetQualities* quality;
-  HXTTetDates* date;
-  uint16_t dateOfLastCheck;
-  uint16_t dateOfLastCreation;
-  HXT2Sync* toSync;
-  // unsigned char* verticesMap;
-  uint64_t maxSearchNodes;
-} HXTSPRData;
-
-
-
 /* hxtSPR_opti() performs an optimization of the quality of a mesh
  * by growing a cavity around the tetrahedron `badTet`
  * and applying hxtSPR repeatedly.
@@ -243,10 +212,16 @@ typedef struct {
  * However, this function requires no knowledge of how SPR works,
  * and no knowledge of the SPRCavity structure.
  *
- *
  * It is meant to be used for mesh optimization in hxt_tetOpti.c
+ *
+ * Possible return status:
+ *    - HXT_STATUS_OK         (on success: cavity improved)
+ *    - HXT_STATUS_ERROR      (on error)
+ *    - HXT_STATUS_CONFLICT   (on conflict with other partition)
+ *    - HXT_STATUS_INTERNAL   (on failure: cavity not improved)
+ *
  */
-HXTStatus hxtSPR_opti(HXTSPRData* data,
+HXTStatus hxtSPR_opti(ThreadLocal* local,
                       uint64_t badTet);
 
 
diff --git a/contrib/hxt/hxt_edgeRemoval.c b/contrib/hxt/tetMesh/src/hxt_edgeRemoval.c
similarity index 77%
rename from contrib/hxt/hxt_edgeRemoval.c
rename to contrib/hxt/tetMesh/src/hxt_edgeRemoval.c
index 679c522fee..76be934860 100644
--- a/contrib/hxt/hxt_edgeRemoval.c
+++ b/contrib/hxt/tetMesh/src/hxt_edgeRemoval.c
@@ -1,8 +1,27 @@
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
 #include "hxt_edgeRemoval.h"
 #include "hxt_tetFlag.h"
 
 
-#define NV -128               // not a valid entry
+#define NV -128                // not a valid entry
+#define HXT_EDGE_REMOVAL_MAX 7 // you cannot increase it above 7 ATM
+
+typedef struct { // bipyramidal cavity for the edge-removal
+    uint64_t neigh_up  [HXT_EDGE_REMOVAL_MAX];
+    uint64_t neigh_down[HXT_EDGE_REMOVAL_MAX];
+    uint16_t flag      [HXT_EDGE_REMOVAL_MAX];
+    uint32_t annulus   [HXT_EDGE_REMOVAL_MAX];
+    uint32_t v_up;
+    uint32_t v_down;
+    uint32_t num;
+} HXTBipyramid;
 
 
 /*
@@ -359,27 +378,28 @@ static const SwapPattern patterns[8] = {
  **************************************************************************/
 
 /* create a cavity containing all tetrahedra around an edge, by turning around it */
-static inline HXTStatus buildEdgeCavity(HXTEdgeRemovalData* data,
-                                        const uint64_t badTet,
-                                        unsigned in_facet, unsigned out_facet)
+static inline HXTStatus buildERCavity(ThreadLocal* local,
+                                      HXTBipyramid* cavity,
+                                      const uint64_t badTet,
+                                      unsigned in_facet, unsigned out_facet)
 {
-  const uint64_t startDist = data->partition->startDist;
-  const uint64_t rel = data->partition->lengthDist;
+  const uint64_t startDist = local->partition.startDist;
+  const uint64_t rel = local->partition.lengthDist;
   int edgeOut = 0;
-  HXTMesh* mesh = data->toSync->mesh;
-  HXTDeleted* deleted = data->deleted;
+  HXTMesh* mesh = local->toSync->mesh;
+  HXTDeleted* deleted = &local->deleted;
   HXTVertex* vertices = (HXTVertex*) mesh->vertices.coord;
 
   uint64_t curTet = badTet;
-  data->cavity.num = 0;
+  cavity->num = 0;
 
   if(getEdgeConstraint(mesh, badTet, getEdgeFromFacets(in_facet, out_facet)))
     return HXT_STATUS_CONSTRAINT;
 
-  data->cavity.v_up = mesh->tetrahedra.node[4*badTet + UP_VERTEX(in_facet, out_facet)];
-  edgeOut += vertexOutOfPartition(vertices, data->cavity.v_up, rel, startDist);
-  data->cavity.v_down = mesh->tetrahedra.node[4*badTet + DOWN_VERTEX(in_facet, out_facet)];
-  edgeOut += vertexOutOfPartition(vertices, data->cavity.v_down, rel, startDist);
+  cavity->v_up = mesh->tetrahedra.node[4*badTet + UP_VERTEX(in_facet, out_facet)];
+  edgeOut += vertexOutOfPartition(vertices, cavity->v_up, rel, startDist);
+  cavity->v_down = mesh->tetrahedra.node[4*badTet + DOWN_VERTEX(in_facet, out_facet)];
+  edgeOut += vertexOutOfPartition(vertices, cavity->v_down, rel, startDist);
 
   HXT_CHECK( askForDeleted(deleted, 7) );
 
@@ -394,15 +414,15 @@ static inline HXTStatus buildEdgeCavity(HXTEdgeRemovalData* data,
     }
 
     // add the current tetrahedra
-    deleted->array[deleted->num + data->cavity.num] = curTet;
+    deleted->array[deleted->num + cavity->num] = curTet;
 
     {
       unsigned up_facet = UP_FACET(in_facet, out_facet);
       unsigned down_facet = DOWN_FACET(in_facet, out_facet);
 
       // add the neighbor up and down
-      data->cavity.neigh_up[data->cavity.num] = mesh->tetrahedra.neigh[4*curTet + up_facet];
-      data->cavity.neigh_down[data->cavity.num] = mesh->tetrahedra.neigh[4*curTet + down_facet];
+      cavity->neigh_up[cavity->num] = mesh->tetrahedra.neigh[4*curTet + up_facet];
+      cavity->neigh_down[cavity->num] = mesh->tetrahedra.neigh[4*curTet + down_facet];
 
       int upDownEdge = getEdgeFromFacets(up_facet, down_facet);
       int upOutEdge = getEdgeFromFacets(up_facet, out_facet);
@@ -412,18 +432,18 @@ static inline HXTStatus buildEdgeCavity(HXTEdgeRemovalData* data,
 
 
       // TODO: just store one flag for up and down. the one of the default tetrahedron
-      data->cavity.flag[data->cavity.num] = (getFacetConstraint(mesh, curTet, up_facet)!=0) +
-                                              ((getEdgeConstraint(mesh, curTet, upOutEdge)!=0)<<1) +
-                                              ((getEdgeConstraint(mesh, curTet, upDownEdge)!=0)<<2) +
-                                              ((getEdgeConstraint(mesh, curTet, upInEdge)!=0)<<3) +
-                                              ((getFacetConstraint(mesh, curTet, down_facet)!=0)<<4) +
-                                              ((getEdgeConstraint(mesh, curTet, downOutEdge)!=0)<<5) +
-                                              ((getEdgeConstraint(mesh, curTet, downInEdge)!=0)<<6) +
-                                              ((getEdgeConstraint(mesh, curTet, upDownEdge)!=0)<<7);
+      cavity->flag[cavity->num] = (getFacetConstraint(mesh, curTet, up_facet)!=0) +
+                                            ((getEdgeConstraint(mesh, curTet, upOutEdge)!=0)<<1) +
+                                            ((getEdgeConstraint(mesh, curTet, upDownEdge)!=0)<<2) +
+                                            ((getEdgeConstraint(mesh, curTet, upInEdge)!=0)<<3) +
+                                            ((getFacetConstraint(mesh, curTet, down_facet)!=0)<<4) +
+                                            ((getEdgeConstraint(mesh, curTet, downOutEdge)!=0)<<5) +
+                                            ((getEdgeConstraint(mesh, curTet, downInEdge)!=0)<<6) +
+                                            ((getEdgeConstraint(mesh, curTet, upDownEdge)!=0)<<7);
     }
     // add the annulus vertex
-    data->cavity.annulus[data->cavity.num] = oldV;
-    data->cavity.num++;
+    cavity->annulus[cavity->num] = oldV;
+    cavity->num++;
 
     // go into the neighbor through out_facet
     uint64_t neigh = mesh->tetrahedra.neigh[4*curTet + out_facet];
@@ -432,7 +452,7 @@ static inline HXTStatus buildEdgeCavity(HXTEdgeRemovalData* data,
       return HXT_STATUS_CONSTRAINT;
     }
 
-    if(data->cavity.num>=HXT_EDGE_REMOVAL_MAX)
+    if(cavity->num>=HXT_EDGE_REMOVAL_MAX)
       return HXT_STATUS_INTERNAL;
 
     curTet = neigh/4;
@@ -453,43 +473,31 @@ static inline HXTStatus buildEdgeCavity(HXTEdgeRemovalData* data,
 
 
 /* perform the edge removal, also called edge swap */
-HXTStatus hxtEdgeRemoval_opti(HXTEdgeRemovalData* data,
+HXTStatus hxtEdgeRemoval_opti(ThreadLocal* local,
                               uint64_t badTet,
                               unsigned edgeID)
 {
   unsigned in_facet, out_facet;
   getFacetsFromEdge(edgeID, &in_facet, &out_facet);
-  HXTMesh* mesh = data->toSync->mesh;
-  HXTBipyramid* cavity = &data->cavity;
-  HXTDeleted* deleted = data->deleted;
-  double* qualityArray = data->quality->values;
-
-  HXT_CHECK( buildEdgeCavity(data, badTet, in_facet, out_facet) );
-
-  // int modified = 0;
-  // for (uint32_t i=0; i<cavity->num; i++) {
-  //   if(getEdgeRemovalFlag(mesh, deleted->array[deleted->num+i])) {
-  //     modified = 1;
-  //     break;
-  //   }
-  // }
+  HXTMesh* mesh = local->toSync->mesh;
+  HXTDeleted* deleted = &local->deleted;
+  double* qualityArray = local->quality->values;
 
-  // if(!modified) {
-  //   return HXT_STATUS_INTERNAL;
-  // }
+  HXTBipyramid cavity;
+  HXT_CHECK( buildERCavity(local, &cavity, badTet, in_facet, out_facet) );
 
   // find worst quality tet of the cavity
   double worst = DBL_MAX;
-  for (uint32_t i=0; i<cavity->num; i++) {
+  for (uint32_t i=0; i<cavity.num; i++) {
     uint64_t tet = deleted->array[deleted->num+i];
     double qual = qualityArray[tet];
     if(qual<worst)
       worst = qual;
   }
 
-  const SwapPattern* patt = &patterns[cavity->num];
-  const unsigned num_triangle_per_triangul = cavity->num-2;
-  uint32_t* annulus = cavity->annulus;
+  const SwapPattern* patt = &patterns[cavity.num];
+  const unsigned num_triangle_per_triangul = cavity.num-2;
+  uint32_t* annulus = cavity.annulus;
 
   // calculate qualities of all possible tetrahedra
   double hxtDeclareAligned qual_up[35];
@@ -502,8 +510,8 @@ HXTStatus hxtEdgeRemoval_opti(HXTEdgeRemovalData* data,
 
     // printf("%u %u %u\n", p0, p1, p2);
 
-    qual_up[i] = tetQuality(mesh, data->quality, p0, p1, cavity->v_up, p2);
-    qual_down[i] = tetQuality(mesh, data->quality, p0, p1, p2, cavity->v_down);
+    qual_up[i] = tetQuality(mesh, local->quality, p0, p1, cavity.v_up, p2);
+    qual_down[i] = tetQuality(mesh, local->quality, p0, p1, p2, cavity.v_down);
 
     if(qual_up[i]<=worst || qual_down[i]<=worst)
       mask |= patt->triangle_in_triangul[i];
@@ -543,15 +551,14 @@ HXTStatus hxtEdgeRemoval_opti(HXTEdgeRemovalData* data,
   }
   
   // mark new deleted tet as deleted
-  for (uint32_t i=0; i<cavity->num; i++) {
-    qualityArray[deleted->array[deleted->num+i]] = DBL_MAX; // deleted tets have good quality
+  for (uint32_t i=0; i<cavity.num; i++) {
     setDeletedFlag(mesh, deleted->array[deleted->num+i]);
   }
-  deleted->num += cavity->num;
+  deleted->num += cavity.num;
 
   // reserve enough tetrahedra
   if(2*num_triangle_per_triangul > deleted->num){ // tetrahedra are created...
-    HXT_CHECK(createNewDeleted(data->toSync, deleted, 2*num_triangle_per_triangul) );
+    HXT_CHECK(createNewDeleted(local->toSync, deleted, 2*num_triangle_per_triangul) );
   }
 
   uint64_t start = deleted->num - 2*num_triangle_per_triangul;
@@ -580,24 +587,24 @@ HXTStatus hxtEdgeRemoval_opti(HXTEdgeRemovalData* data,
       mesh->tetrahedra.colors[newTet_up] = color;
       mesh->tetrahedra.flag[newTet_up] = 0;
       qualityArray[newTet_up] = qual_up[tri];
-      data->date->values[newTet_up].creation = data->date->current;
+      local->date->values[newTet_up].creation = local->date->current;
 
       nodes[0] = p0;
       nodes[1] = p1;
-      nodes[2] = cavity->v_up;
+      nodes[2] = cavity.v_up;
       nodes[3] = p2;
 
       if(n0>=0){                                                     //  v   we add this because if n0%4==2 then it should be 3
         neigh[0] = 4*deleted->array[start + (n0/4)*2] + (n0%4) + (n0%4)/2;
       }
       else {
-        neigh[0] = cavity->neigh_up[-n0-1];
+        neigh[0] = cavity.neigh_up[-n0-1];
 
         //  (down=2, in=3, out=1, up=0)
-        mesh->tetrahedra.flag[newTet_up] |= (cavity->flag[-n0-1]&UINT16_C(1))<<8 |// face (bit 0) is the up_facet => 0  (bit 8)
-                                            (cavity->flag[-n0-1]&UINT16_C(2))>>1 |// first edge (bit 1) was between up_facet and out_facet => 0-1  (bit 0)
-                                            (cavity->flag[-n0-1]&UINT16_C(4))>>1 |// second edge (bit 2) was between up_facet and down_facet => 0-2 (bit 1)
-                                            (cavity->flag[-n0-1]&UINT16_C(8))>>1; // third edge (bit 3) was between up_facet and in_facet => 0-3    (bit 2)
+        mesh->tetrahedra.flag[newTet_up] |= (cavity.flag[-n0-1]&UINT16_C(1))<<8 |// face (bit 0) is the up_facet => 0  (bit 8)
+                                            (cavity.flag[-n0-1]&UINT16_C(2))>>1 |// first edge (bit 1) was between up_facet and out_facet => 0-1  (bit 0)
+                                            (cavity.flag[-n0-1]&UINT16_C(4))>>1 |// second edge (bit 2) was between up_facet and down_facet => 0-2 (bit 1)
+                                            (cavity.flag[-n0-1]&UINT16_C(8))>>1; // third edge (bit 3) was between up_facet and in_facet => 0-3    (bit 2)
 
         if(neigh[0]!=HXT_NO_ADJACENT)
           mesh->tetrahedra.neigh[neigh[0]] = 4*newTet_up + 0;
@@ -606,13 +613,13 @@ HXTStatus hxtEdgeRemoval_opti(HXTEdgeRemovalData* data,
         neigh[1] = 4*deleted->array[start + (n1/4)*2] + (n1%4) + (n1%4)/2;
       }
       else {
-        neigh[1] = cavity->neigh_up[-n1-1];
+        neigh[1] = cavity.neigh_up[-n1-1];
 
         //  (down=2, in=0, out=3, up=1)
-        mesh->tetrahedra.flag[newTet_up] |= (cavity->flag[-n1-1]&UINT16_C(1))<<9 |// face (bit 0) is the up_facet => 1  (bit 9)
-                                            (cavity->flag[-n1-1]&UINT16_C(2))<<3 |// first edge (bit 1) was between up_facet and out_facet => 1-3   (bit 4)
-                                            (cavity->flag[-n1-1]&UINT16_C(4))<<1 |// second edge (bit 2) was between up_facet and down_facet => 1-2 (bit 3)
-                                            (cavity->flag[-n1-1]&UINT16_C(8))>>3; // third edge (bit 3) was between up_facet and in_facet => 0-1    (bit 0)
+        mesh->tetrahedra.flag[newTet_up] |= (cavity.flag[-n1-1]&UINT16_C(1))<<9 |// face (bit 0) is the up_facet => 1  (bit 9)
+                                            (cavity.flag[-n1-1]&UINT16_C(2))<<3 |// first edge (bit 1) was between up_facet and out_facet => 1-3   (bit 4)
+                                            (cavity.flag[-n1-1]&UINT16_C(4))<<1 |// second edge (bit 2) was between up_facet and down_facet => 1-2 (bit 3)
+                                            (cavity.flag[-n1-1]&UINT16_C(8))>>3; // third edge (bit 3) was between up_facet and in_facet => 0-1    (bit 0)
 
         if(neigh[1]!=HXT_NO_ADJACENT)
           mesh->tetrahedra.neigh[neigh[1]] = 4*newTet_up + 1;
@@ -622,13 +629,13 @@ HXTStatus hxtEdgeRemoval_opti(HXTEdgeRemovalData* data,
         neigh[3] = 4*deleted->array[start + (n2/4)*2] + (n2%4) + (n2%4)/2;
       }
       else {
-        neigh[3] = cavity->neigh_up[-n2-1];
+        neigh[3] = cavity.neigh_up[-n2-1];
 
         //  (down=2, in=1, out=0, up=3)
-        mesh->tetrahedra.flag[newTet_up] |= (cavity->flag[-n2-1]&UINT16_C(1))<<11 |// face (bit 0) is the up_facet => 3  (bit 11)
-                                            (cavity->flag[-n2-1]&UINT16_C(2))<<1  |// first edge (bit 1) was between up_facet and out_facet => 0-3   (bit 2)
-                                            (cavity->flag[-n2-1]&UINT16_C(4))<<3  |// second edge (bit 2) was between up_facet and down_facet => 2-3 (bit 5)
-                                            (cavity->flag[-n2-1]&UINT16_C(8))<<1;  // third edge (bit 3) was between up_facet and in_facet => 1-3    (bit 4)
+        mesh->tetrahedra.flag[newTet_up] |= (cavity.flag[-n2-1]&UINT16_C(1))<<11 |// face (bit 0) is the up_facet => 3  (bit 11)
+                                            (cavity.flag[-n2-1]&UINT16_C(2))<<1  |// first edge (bit 1) was between up_facet and out_facet => 0-3   (bit 2)
+                                            (cavity.flag[-n2-1]&UINT16_C(4))<<3  |// second edge (bit 2) was between up_facet and down_facet => 2-3 (bit 5)
+                                            (cavity.flag[-n2-1]&UINT16_C(8))<<1;  // third edge (bit 3) was between up_facet and in_facet => 1-3    (bit 4)
 
         if(neigh[3]!=HXT_NO_ADJACENT)
           mesh->tetrahedra.neigh[neigh[3]] = 4*newTet_up + 3;
@@ -643,24 +650,24 @@ HXTStatus hxtEdgeRemoval_opti(HXTEdgeRemovalData* data,
       mesh->tetrahedra.colors[newTet_down] = color;
       mesh->tetrahedra.flag[newTet_down] = 0;
       qualityArray[newTet_down] = qual_down[tri];
-      data->date->values[newTet_down].creation = data->date->current;
+      local->date->values[newTet_down].creation = local->date->current;
 
       nodes[0] = p0;
       nodes[1] = p1;
       nodes[2] = p2;
-      nodes[3] = cavity->v_down;
+      nodes[3] = cavity.v_down;
 
       if(n0>=0){
         neigh[0] = 4*deleted->array[start + (n0/4)*2 +1] + (n0%4);
       }
       else {
-        neigh[0] = cavity->neigh_down[-n0-1];
+        neigh[0] = cavity.neigh_down[-n0-1];
 
         //  (down=0, in=2, out=1, up=3)
-        mesh->tetrahedra.flag[newTet_down] |= (cavity->flag[-n0-1]&UINT16_C(16))<<4 |// face (bit 4) is the down_facet => 0  (bit 8)
-                                              (cavity->flag[-n0-1]&UINT16_C(32))>>5 |// first edge (bit 5) was between down_facet and out_facet => 0-1   (bit 0)
-                                              (cavity->flag[-n0-1]&UINT16_C(64))>>5 |// second edge (bit 6) was between down_facet and in_facet => 0-2   (bit 1)
-                                              (cavity->flag[-n0-1]&UINT16_C(128))>>5;// third edge (bit 7) was between down_facet and up_facet => 0-3    (bit 2)
+        mesh->tetrahedra.flag[newTet_down] |= (cavity.flag[-n0-1]&UINT16_C(16))<<4 |// face (bit 4) is the down_facet => 0  (bit 8)
+                                              (cavity.flag[-n0-1]&UINT16_C(32))>>5 |// first edge (bit 5) was between down_facet and out_facet => 0-1   (bit 0)
+                                              (cavity.flag[-n0-1]&UINT16_C(64))>>5 |// second edge (bit 6) was between down_facet and in_facet => 0-2   (bit 1)
+                                              (cavity.flag[-n0-1]&UINT16_C(128))>>5;// third edge (bit 7) was between down_facet and up_facet => 0-3    (bit 2)
 
         if(neigh[0]!=HXT_NO_ADJACENT)
           mesh->tetrahedra.neigh[neigh[0]] = 4*newTet_down + 0;
@@ -669,13 +676,13 @@ HXTStatus hxtEdgeRemoval_opti(HXTEdgeRemovalData* data,
         neigh[1] = 4*deleted->array[start + (n1/4)*2 +1] + (n1%4);
       }
       else {
-        neigh[1] = cavity->neigh_down[-n1-1];
+        neigh[1] = cavity.neigh_down[-n1-1];
 
         //  (down=1, in=0, out=2, up=3)
-        mesh->tetrahedra.flag[newTet_down] |= (cavity->flag[-n1-1]&UINT16_C(16))<<5 |// face (bit 4) is the down_facet => 1  (bit 9)
-                                              (cavity->flag[-n1-1]&UINT16_C(32))>>2 |// first edge (bit 5) was between down_facet and out_facet => 1-2   (bit 3)
-                                              (cavity->flag[-n1-1]&UINT16_C(64))>>6 |// second edge (bit 6) was between down_facet and in_facet => 0-1   (bit 0)
-                                              (cavity->flag[-n1-1]&UINT16_C(128))>>3;// third edge (bit 7) was between down_facet and up_facet => 1-3    (bit 4)
+        mesh->tetrahedra.flag[newTet_down] |= (cavity.flag[-n1-1]&UINT16_C(16))<<5 |// face (bit 4) is the down_facet => 1  (bit 9)
+                                              (cavity.flag[-n1-1]&UINT16_C(32))>>2 |// first edge (bit 5) was between down_facet and out_facet => 1-2   (bit 3)
+                                              (cavity.flag[-n1-1]&UINT16_C(64))>>6 |// second edge (bit 6) was between down_facet and in_facet => 0-1   (bit 0)
+                                              (cavity.flag[-n1-1]&UINT16_C(128))>>3;// third edge (bit 7) was between down_facet and up_facet => 1-3    (bit 4)
 
         if(neigh[1]!=HXT_NO_ADJACENT)
           mesh->tetrahedra.neigh[neigh[1]] = 4*newTet_down + 1;
@@ -684,13 +691,13 @@ HXTStatus hxtEdgeRemoval_opti(HXTEdgeRemovalData* data,
         neigh[2] = 4*deleted->array[start + (n2/4)*2 +1] + (n2%4);
       }
       else {
-        neigh[2] = cavity->neigh_down[-n2-1];
+        neigh[2] = cavity.neigh_down[-n2-1];
 
         //  (down=2, in=1, out=0, up=3)
-        mesh->tetrahedra.flag[newTet_down] |= (cavity->flag[-n2-1]&UINT16_C(16))<<6 |// face (bit 4) is the down_facet => 2*4  (bit 10)
-                                              (cavity->flag[-n2-1]&UINT16_C(32))>>4 |// first edge (bit 5) was between down_facet and out_facet => 0-2   (bit 1)
-                                              (cavity->flag[-n2-1]&UINT16_C(64))>>3 |// second edge (bit 6) was between down_facet and in_facet => 1-2   (bit 3)
-                                              (cavity->flag[-n2-1]&UINT16_C(128))>>2;// third edge (bit 7) was between down_facet and up_facet => 2-3    (bit 5)
+        mesh->tetrahedra.flag[newTet_down] |= (cavity.flag[-n2-1]&UINT16_C(16))<<6 |// face (bit 4) is the down_facet => 2*4  (bit 10)
+                                              (cavity.flag[-n2-1]&UINT16_C(32))>>4 |// first edge (bit 5) was between down_facet and out_facet => 0-2   (bit 1)
+                                              (cavity.flag[-n2-1]&UINT16_C(64))>>3 |// second edge (bit 6) was between down_facet and in_facet => 1-2   (bit 3)
+                                              (cavity.flag[-n2-1]&UINT16_C(128))>>2;// third edge (bit 7) was between down_facet and up_facet => 2-3    (bit 5)
 
         if(neigh[2]!=HXT_NO_ADJACENT)
           mesh->tetrahedra.neigh[neigh[2]] = 4*newTet_down + 2;
diff --git a/contrib/hxt/tetMesh/src/hxt_edgeRemoval.h b/contrib/hxt/tetMesh/src/hxt_edgeRemoval.h
new file mode 100644
index 0000000000..3d1452bf0e
--- /dev/null
+++ b/contrib/hxt/tetMesh/src/hxt_edgeRemoval.h
@@ -0,0 +1,26 @@
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
+#ifndef HXT_EDGEREMOVAL_H
+#define HXT_EDGEREMOVAL_H
+
+#include "hxt_tetOptiUtils.h"
+
+
+/* return internal error (that you must catch) if:
+ *    - the cavity overlap different partitions  => HXT_STATUS_CONFLICT
+ *    - there is a contraint inside the cavity   => HXT_STATUS_CONSTRAINT
+ *    - does'nt result in a better triangulation => HXT_STATUS_NOTBETTER
+ *    - there is more than 7 pts around the edge => HXT_STATUS_INTERNAL
+ * a facet without neighbor (set to HXT_NO_ADJACENT) is also a constraint.
+ */
+HXTStatus hxtEdgeRemoval_opti(ThreadLocal* local,
+                              uint64_t badTet,
+                              unsigned edgeID);
+
+#endif
\ No newline at end of file
diff --git a/contrib/hxt/hxt_smoothing.c b/contrib/hxt/tetMesh/src/hxt_smoothing.c
similarity index 84%
rename from contrib/hxt/hxt_smoothing.c
rename to contrib/hxt/tetMesh/src/hxt_smoothing.c
index 7be04c5d06..6edc6e727f 100644
--- a/contrib/hxt/hxt_smoothing.c
+++ b/contrib/hxt/tetMesh/src/hxt_smoothing.c
@@ -1,3 +1,11 @@
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
 #include "hxt_smoothing.h"
 #include "hxt_tetFlag.h"
 
@@ -5,17 +13,17 @@
                     smoothing related functions
  **************************************************************************/
 /* create a cavity containing all tetrahedra around a vertex, with a BFS */
-static inline HXTStatus buildSmoothingCavity(HXTSmoothingData* data,
+static inline HXTStatus buildSmoothingCavity(ThreadLocal* local,
                                              uint64_t startFace) {
-  const uint64_t startDist = data->partition->startDist;
-  const uint64_t rel = data->partition->lengthDist;
-  HXTMesh* mesh = data->mesh;
+  const uint64_t startDist = local->partition.startDist;
+  const uint64_t rel = local->partition.lengthDist;
+  HXTMesh* mesh = local->toSync->mesh;
   const uint32_t vertex = mesh->tetrahedra.node[startFace];
   HXTVertex* vertices = (HXTVertex*) mesh->vertices.coord;
-  HXTDeleted* deleted = data->deleted;
+  HXTDeleted* deleted = &local->deleted;
 
   
-  if(vertex < data->numVerticesConstrained)
+  if(vertex < local->numVerticesConstrained)
     return HXT_STATUS_CONSTRAINT;
 
   // the vertex we are moving should be in the partition or we don't even try...
@@ -23,7 +31,7 @@ static inline HXTStatus buildSmoothingCavity(HXTSmoothingData* data,
     return HXT_STATUS_CONFLICT;
   }
 
-  HXT_CHECK( askForDeleted(data->deleted, 4) );
+  HXT_CHECK( askForDeleted(&local->deleted, 4) );
   deleted->array[deleted->num++] = startFace;
   setDeletedFlag(mesh, startFace/4);
 
@@ -70,7 +78,7 @@ static inline HXTStatus buildSmoothingCavity(HXTSmoothingData* data,
       // we can add the face without any fears now, but we have to find where is the vertex
       for (unsigned k=1; k<4; k++) {
         if(mesh->tetrahedra.node[4*neighTet + (neighF+k)%4]==vertex) {
-          deleted->array[data->deleted->num++] = 4*neighTet + (neighF+k)%4;
+          deleted->array[local->deleted.num++] = 4*neighTet + (neighF+k)%4;
           break;
         }
       }
@@ -109,15 +117,15 @@ static inline void interpolate_coord(const double start[3], const double end[3],
   }
 }
 
-static HXTStatus golden_section_search(HXTSmoothingData* data,
+static HXTStatus golden_section_search(ThreadLocal* local,
                                        uint64_t prevNumDeleted,
                                        double start[3],
                                        double end[3],
                                        uint32_t vertex)
 {
-  HXTMesh* mesh = data->mesh;
-  HXTDeleted* deleted = data->deleted;
-  HXTTetQualities* quality = data->quality;
+  HXTMesh* mesh = local->toSync->mesh;
+  HXTDeleted* deleted = &local->deleted;
+  HXTTetQualities* quality = local->quality;
 
   double* coord = mesh->vertices.coord + 4*vertex;
   double tol = 0.00001;
@@ -173,29 +181,31 @@ static HXTStatus golden_section_search(HXTSmoothingData* data,
 
   interpolate_coord(start, end, coord, v[0]);
 
-  // compute new qualities and set new dates
-  for (uint64_t i=prevNumDeleted; i<data->deleted->num; i++) {
-    uint64_t tet = data->deleted->array[i]/4;
+  // compute new qualities and set new dates and reset "unused" flags
+  for (uint64_t i=prevNumDeleted; i<local->deleted.num; i++) {
+    uint64_t tet = local->deleted.array[i]/4;
     quality->values[tet] = tetQuality(mesh, quality,
                                    mesh->tetrahedra.node[4*tet + 0],
                                    mesh->tetrahedra.node[4*tet + 1],
                                    mesh->tetrahedra.node[4*tet + 2],
                                    mesh->tetrahedra.node[4*tet + 3]);
-    data->date->values[tet].creation = data->date->current;
+    // unused flag should be set to zero
+    resetUnusedFlags(mesh, tet);
+    local->date->values[tet].creation = local->date->current;
   }
 
   return HXT_STATUS_OK;
 }
 
 /* curFace is the face opposite to the vertex we are going to move */
-HXTStatus hxtSmoothing(HXTSmoothingData* data,
+HXTStatus hxtSmoothing(ThreadLocal* local,
                        uint64_t curFace)
 {
-  HXTMesh* mesh = data->mesh;
-  HXTDeleted* deleted = data->deleted;
+  HXTMesh* mesh = local->toSync->mesh;
+  HXTDeleted* deleted = &local->deleted;
   uint64_t prevNumDeleted = deleted->num;
 
-  HXTStatus status = buildSmoothingCavity(data, curFace);
+  HXTStatus status = buildSmoothingCavity(local, curFace);
 
   for (uint64_t i=prevNumDeleted; i<deleted->num; i++) {
     unsetDeletedFlag(mesh, deleted->array[i]/4);
@@ -231,7 +241,7 @@ HXTStatus hxtSmoothing(HXTSmoothingData* data,
     centerCoord[j] /= (double) numTetInCavity ;
   }
 
-  status = golden_section_search(data, prevNumDeleted, oldCoord, centerCoord, vertex);
+  status = golden_section_search(local, prevNumDeleted, oldCoord, centerCoord, vertex);
   deleted->num = prevNumDeleted;
 
   if(status!=HXT_STATUS_OK)
diff --git a/contrib/hxt/hxt_smoothing.h b/contrib/hxt/tetMesh/src/hxt_smoothing.h
similarity index 50%
rename from contrib/hxt/hxt_smoothing.h
rename to contrib/hxt/tetMesh/src/hxt_smoothing.h
index af6b1a30f0..6e747ddc5c 100644
--- a/contrib/hxt/hxt_smoothing.h
+++ b/contrib/hxt/tetMesh/src/hxt_smoothing.h
@@ -1,33 +1,28 @@
-#ifndef _HXT_SMOOTHING_
-#define _HXT_SMOOTHING_
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
+#ifndef HXT_SMOOTHING_H
+#define HXT_SMOOTHING_H
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-#include "hxt_tetSync.h"
-#include "hxt_tetPartition.h"
-#include "hxt_tetQuality.h"
-#include "hxt_tetOptiDate.h"
-
-typedef struct {
-  HXTMesh *mesh;
-  HXTDeleted* deleted;
-  HXTPartition* partition;
-  HXTTetQualities* quality;
-  HXTTetDates* date;
-  uint32_t numVerticesConstrained;
-} HXTSmoothingData;
-
+#include "hxt_tetOptiUtils.h"
 
 /* return internal error (that you must catch) if:
  *    - the cavity overlap different partitions  => HXT_STATUS_CONFLICT
  *    - there is a contraint inside the cavity   => HXT_STATUS_CONSTRAINT
- *    - does'nt result in a better triangulation => HXT_STATUS_NOTBETTER
+ *    - does'nt result in a better triangulation => HXT_STATUS_INTERNAL
  * a facet without neighbor (set to HXT_NO_ADJACENT) is also a constraint
  * a node n with n<numVerticesConstrained has its position constrained
  */
-HXTStatus hxtSmoothing(HXTSmoothingData* data,
+HXTStatus hxtSmoothing(ThreadLocal* local,
                        uint64_t oppositeFacet);
 
 
diff --git a/contrib/hxt/hxt_tetColor.c b/contrib/hxt/tetMesh/src/hxt_tetColor.c
similarity index 99%
rename from contrib/hxt/hxt_tetColor.c
rename to contrib/hxt/tetMesh/src/hxt_tetColor.c
index cc4c9d3c3b..e8f1309240 100644
--- a/contrib/hxt/hxt_tetColor.c
+++ b/contrib/hxt/tetMesh/src/hxt_tetColor.c
@@ -1,3 +1,11 @@
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
 #include "hxt_tetColor.h"
 #include "hxt_tetFlag.h"
 #include "hxt_sort.h"
diff --git a/contrib/hxt/hxt_tetColor.h b/contrib/hxt/tetMesh/src/hxt_tetColor.h
similarity index 82%
rename from contrib/hxt/hxt_tetColor.h
rename to contrib/hxt/tetMesh/src/hxt_tetColor.h
index 8a841956d8..cec29d9c9a 100644
--- a/contrib/hxt/hxt_tetColor.h
+++ b/contrib/hxt/tetMesh/src/hxt_tetColor.h
@@ -1,5 +1,13 @@
-#ifndef _HXT_TETCOLOR_
-#define _HXT_TETCOLOR_
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
+#ifndef HXT_TETCOLOR_H
+#define HXT_TETCOLOR_H
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/contrib/hxt/hxt_tetDelaunay.c b/contrib/hxt/tetMesh/src/hxt_tetDelaunay.c
similarity index 82%
rename from contrib/hxt/hxt_tetDelaunay.c
rename to contrib/hxt/tetMesh/src/hxt_tetDelaunay.c
index 0e99b188f1..263239aca9 100644
--- a/contrib/hxt/hxt_tetDelaunay.c
+++ b/contrib/hxt/tetMesh/src/hxt_tetDelaunay.c
@@ -1,3 +1,11 @@
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
 #include "hxt_tetDelaunay.h"
 #include "predicates.h"
 #include "hxt_tetSync.h"
@@ -12,22 +20,23 @@
 */
 
 /* compile-time parameters */
-#define SMALLEST_ROUND 2048
 // #define HXT_DELAUNAY_LOW_MEMORY /* doesn't use any buffer (a lot slower, except if you are at the limit of filling the RAM) */
 // #define HXT_WALK_OPTI
 
+#define SMALLEST_PASS 2048
+
+
 /* usefull macros */
 #define HXT_OMP_CHECK(status) do{ HXTStatus _tmp_ = (status); \
     if(_tmp_<0){ \
       if(_tmp_>HXT_STATUS_INTERNAL) \
         HXT_TRACE_MSG(_tmp_, "cannot break OpenMP region -> exiting"); \
-      fflush(stdout); fflush(stderr); \
       exit(_tmp_); \
     } \
   }while(0)
 
 
-typedef struct{
+typedef struct {
   uint64_t neigh; // the tet on the other side of the boundary
   uint32_t node[3];
   uint16_t flag;
@@ -50,6 +59,17 @@ typedef struct {
 } TetLocal;
 
 
+static int compareNodeLexicographically(uint32_t* nodes0, uint32_t* nodes1)
+{
+  for(int i=0; i<4; i++) {
+    if(nodes0[i] < nodes1[i])
+      return -1;
+    else if(nodes0[i] > nodes1[i])
+      return 1;
+  }
+  return 0;
+}
+
 
 /***********************************
  * create the initial tetrahedron 
@@ -57,10 +77,11 @@ typedef struct {
  ***********************************/
 static inline HXTStatus hxtTetrahedraInit(HXTMesh* mesh, hxtNodeInfo* nodeInfo, uint32_t nToInsert, int verbosity){
   if(nToInsert < 4){
-    return HXT_ERROR_MSG(HXT_STATUS_ERROR, "cannot mesh less than four vertices");
+    return HXT_ERROR_MSG(HXT_STATUS_ERROR, "cannot mesh less than four points");
   }
   if(mesh->tetrahedra.size < 5){
-    uint32_t maxSizeEstim = MAX(omp_get_max_threads()*DELETED_BUFFER_SIZE+8UL*nToInsert, 10UL*nToInsert);
+    uint64_t sizeEstim = omp_get_max_threads()*DELETED_BUFFER_SIZE+8UL*nToInsert;
+    uint64_t maxSizeEstim = MAX(sizeEstim, 10UL*nToInsert);
     HXT_CHECK( hxtTetrahedraReserve(mesh, maxSizeEstim) );
     HXT_INFO_COND(verbosity>1, "Initialization reserved %lu Tet.", mesh->tetrahedra.size);
   }
@@ -163,18 +184,26 @@ static inline HXTStatus hxtTetrahedraInit(HXTMesh* mesh, hxtNodeInfo* nodeInfo,
   return HXT_STATUS_OK;
 }
 
+
 /***********************************
  * fill the passes array which tells
  * the size of each BRIO round.
  * return the number of BRIO passes
  ***********************************/
-static unsigned computePasses(uint32_t passes[12], uint32_t nInserted, uint32_t nToInsert)
+unsigned computePasses(uint32_t passes[12],
+                       uint32_t nInserted,
+                       uint32_t nToInsert,
+                       double partitionability,
+                       int maxThreads)
 {
+  double alpha = 1.0/(maxThreads*maxThreads);
+  nInserted *= ((1.0 - alpha) * partitionability + alpha);
+
   unsigned npasses=0;
   passes[0] = nToInsert;
 
   for (unsigned i=0; i<10; i++) {
-    if(passes[i] < SMALLEST_ROUND || passes[i]/8 < nInserted){
+    if(passes[i] < SMALLEST_PASS || passes[i]/8 < nInserted){
       passes[i+1] = 0;
       npasses = i+1;
       break;
@@ -211,6 +240,7 @@ static inline HXTStatus localInit(TetLocal* local){
 
   local->deleted.size = DELETED_BUFFER_SIZE;
   local->deleted.num = 0;
+  local->deleted.createdNew = 0;
   HXT_CHECK( hxtAlignedMalloc(&local->deleted.array, sizeof(uint64_t)*local->deleted.size) );
 
   return HXT_STATUS_OK;
@@ -221,13 +251,13 @@ static inline HXTStatus localInit(TetLocal* local){
  * check if a tetrahedra is entirely
  * in the calling thread's partition
  ***********************************/
-static inline HXTStatus checkTetrahedron(HXTVertex* vertices, TetLocal* local, const uint32_t* nodes){
+static inline HXTStatus checkTetrahedron(HXTVertex* vertices, HXTPartition* partition, const uint32_t* nodes){
   /* Actually, one vertex (not more) could be in another partition without creating a conflict.
    However, all threads would have to have a verticesID array => a lot of memory space wasted.
    Instead, we only allow the ghost vertex to be in another partition, it is handled differently in
    computeAdjacenciesFast function */
-  uint64_t len = local->partition.lengthDist;
-  uint64_t start = local->partition.startDist;
+  uint64_t len = partition->lengthDist;
+  uint64_t start = partition->startDist;
 
   // if(local->partition.lengthDist==UINT64_MAX) // if we are working with one thread only
   //   return HXT_STATUS_OK;
@@ -919,8 +949,9 @@ static inline HXTStatus diggingACavity(HXTMesh* mesh, TetLocal* local, uint64_t
       }
       else{
         uint32_t node = mesh->tetrahedra.node[curNeigh[0]];
-        if(node!=HXT_GHOST_VERTEX && vertexOutOfPartition(vertices, node, rel, local->partition.startDist))
+        if(node!=HXT_GHOST_VERTEX && vertexOutOfPartition(vertices, node, rel, local->partition.startDist)) {
           return HXT_STATUS_CONFLICT;
+        }
         local->deleted.array[local->deleted.num++] = neigh;
         setDeletedFlag(mesh, neigh);
       }
@@ -938,8 +969,9 @@ static inline HXTStatus diggingACavity(HXTMesh* mesh, TetLocal* local, uint64_t
       }
       else{
         uint32_t node = mesh->tetrahedra.node[curNeigh[1]];
-        if(node!=HXT_GHOST_VERTEX && vertexOutOfPartition(vertices, node, rel, local->partition.startDist))
+        if(node!=HXT_GHOST_VERTEX && vertexOutOfPartition(vertices, node, rel, local->partition.startDist)) {
           return HXT_STATUS_CONFLICT;
+        }
         local->deleted.array[local->deleted.num++] = neigh;
         setDeletedFlag(mesh, neigh);
       }
@@ -957,8 +989,9 @@ static inline HXTStatus diggingACavity(HXTMesh* mesh, TetLocal* local, uint64_t
       }
       else{
         uint32_t node = mesh->tetrahedra.node[curNeigh[2]];
-        if(node!=HXT_GHOST_VERTEX && vertexOutOfPartition(vertices, node, rel, local->partition.startDist))
+        if(node!=HXT_GHOST_VERTEX && vertexOutOfPartition(vertices, node, rel, local->partition.startDist)) {
           return HXT_STATUS_CONFLICT;
+        }
         local->deleted.array[local->deleted.num++] = neigh;
         setDeletedFlag(mesh, neigh);
       }
@@ -978,8 +1011,9 @@ static inline HXTStatus diggingACavity(HXTMesh* mesh, TetLocal* local, uint64_t
       }
       else{
         uint32_t node = mesh->tetrahedra.node[curNeigh[3]];
-        if(node!=HXT_GHOST_VERTEX && vertexOutOfPartition(vertices, node, rel, local->partition.startDist))
+        if(node!=HXT_GHOST_VERTEX && vertexOutOfPartition(vertices, node, rel, local->partition.startDist)) {
           return HXT_STATUS_CONFLICT;
+        }
         local->deleted.array[local->deleted.num++] = neigh;
         setDeletedFlag(mesh, neigh);
       }
@@ -1248,6 +1282,43 @@ static HXTStatus insertion(HXT2Sync* shared2sync,
   return HXT_STATUS_TRUE;
 }
 
+/* filter vertices that are too close from each other,
+ * returns the number of filtered vertices */
+// TODO: this should be done way before assigning partition
+// it should be used to identify a possible imbalance ahead of time !
+static inline uint32_t filterOnMooreCurve(HXTVertex* vertices,
+                                          hxtNodeInfo* nodeInfo,
+                                          uint32_t n,
+                                          double* nodalSizes)
+{
+  uint32_t mooreSkipped = 0;
+  #pragma omp parallel reduction(+:mooreSkipped)
+  {
+    double* p1 = NULL;
+    double p1Size = 0;
+
+    #pragma omp for
+    for (uint32_t i=0; i<n; i++)
+    {
+      uint32_t lastNode = nodeInfo[i].node;
+      if(nodeInfo[i].status==HXT_STATUS_TRYAGAIN){
+        double* p2 = vertices[lastNode].coord;
+        double p2Size = nodalSizes[lastNode];
+        if(p1!=NULL && pointIsTooClose(p1, p2, 0.5*(p1Size+p2Size))!=HXT_STATUS_OK){
+          mooreSkipped++;
+          nodeInfo[i].status=HXT_STATUS_FALSE;
+        }
+        else{
+          p1 = p2;
+          p1Size = p2Size;
+        }
+      }
+    }
+  }
+
+  return mooreSkipped;
+}
+
 
 /*************************************************************
  * Delaunay triangulation of a set of points
@@ -1258,7 +1329,9 @@ static HXTStatus parallelDelaunay3D(HXTMesh* mesh,
                                     const uint32_t nToInsert,
                                     int noReordering)
 {
+  int nonDeterministic = 0;
   uint32_t totalNumSkipped = 0;
+  uint32_t totalNumInserted = 0;
   uint32_t seed = 1;
 
   // third, divide indices in different passes
@@ -1266,7 +1339,7 @@ static HXTStatus parallelDelaunay3D(HXTMesh* mesh,
   const int perfectlyDelaunay = mesh->tetrahedra.num<=5;
 
   uint32_t passes[12];
-  unsigned npasses = computePasses(passes, options->numVerticesInMesh, nToInsert);
+  unsigned npasses = computePasses(passes, options->numVerticesInMesh, nToInsert, options->partitionability, maxThreads);
 
   // that ugly cast because people want an array of double into the mesh structure
   HXTVertex* vertices = (HXTVertex*) mesh->vertices.coord;
@@ -1274,44 +1347,58 @@ static HXTStatus parallelDelaunay3D(HXTMesh* mesh,
   /******************************************************
           shuffle (and optimize cache locality)
   ******************************************************/
-  if(noReordering){
-    // shuffle nodeInfo
-    if(npasses>1)
-      HXT_CHECK( hxtNodeInfoShuffle(nodeInfo, nToInsert) );
-  }
-  else {
-    HXT_INFO_COND(options->verbosity>1, "Reordering vertices from %u to %u", mesh->vertices.num - nToInsert, mesh->vertices.num);
-    HXTVertex* verticesToInsert = vertices + mesh->vertices.num - nToInsert;
-
-    if(options->nodalSizes==NULL){
-      // shuffle the vertices to insert, then sort each pass except the first according to the hilbert curve...
-      if(npasses>1)
-        HXT_CHECK( hxtVerticesShuffle(verticesToInsert, nToInsert) );
+  int firstPassEver = (options->numVerticesInMesh==0);
+  uint32_t firstToInsert = mesh->vertices.num - nToInsert;
+  HXT_INFO_COND(options->verbosity>1, "Reordering points from %u to %u", mesh->vertices.num - nToInsert, mesh->vertices.num);
+  HXTVertex* verticesToInsert = vertices + mesh->vertices.num - nToInsert;
+
+  int defaultMooreCurve = 1;
+
+  if(options->nodalSizes==NULL && !noReordering){
+    // shuffle the vertices to insert, then sort each pass except the first according to the hilbert curve...
+    if(npasses>1 || firstPassEver){
+      HXT_CHECK( hxtVerticesShuffle(verticesToInsert, nToInsert) );
     }
-    else{
-      if(npasses>1)
-        HXT_CHECK( hxtNodeInfoShuffle(nodeInfo, nToInsert) );
+
+    HXT_CHECK( hxtMoore(options->bbox, vertices, mesh->vertices.num, NULL) );
+
+    for (unsigned i=firstPassEver; i<npasses; i++) {
+      HXT_CHECK( hxtVerticesSort(verticesToInsert+passes[i], passes[i+1]-passes[i]) );
     }
-    
-    HXT_CHECK( hxtMoore(options->bbox, verticesToInsert, nToInsert, NULL) );
 
-    if(options->nodalSizes==NULL){
-      for (unsigned i=options->numVerticesInMesh < SMALLEST_ROUND; i<npasses; i++) {
-        HXT_CHECK( hxtVerticesSort(verticesToInsert+passes[i], passes[i+1]-passes[i]) );
-      }
+    #pragma omp parallel for simd aligned(nodeInfo:SIMD_ALIGN)
+    for (uint32_t i=0; i<nToInsert; i++) {
+      nodeInfo[i].node = firstToInsert + i;
+      nodeInfo[i].status = HXT_STATUS_TRYAGAIN;
+      nodeInfo[i].hilbertDist = verticesToInsert[i].padding.hilbertDist;
     }
-    else{
-      #pragma omp parallel for
+  }
+  else{
+
+    HXT_CHECK( hxtMoore(options->bbox, vertices, mesh->vertices.num, NULL) );
+
+    if(!noReordering) {
+      #pragma omp parallel for simd aligned(nodeInfo:SIMD_ALIGN)
       for (uint32_t i=0; i<nToInsert; i++) {
-        nodeInfo[i].hilbertDist = verticesToInsert[i].padding.hilbertDist;
+        nodeInfo[i].node = firstToInsert + i;
+        nodeInfo[i].status = HXT_STATUS_TRYAGAIN;
       }
+    }
 
-      for (unsigned i=options->numVerticesInMesh < SMALLEST_ROUND; i<npasses; i++) {
-        HXT_CHECK( hxtNodeInfoSort(nodeInfo+passes[i], passes[i+1]-passes[i]) );
-      }
+    if(npasses>1 || firstPassEver)
+      HXT_CHECK( hxtNodeInfoShuffle(nodeInfo, nToInsert) );
 
-      const uint32_t nodalMin = mesh->vertices.num - nToInsert;
-      double* sizesToInsert = options->nodalSizes + nodalMin;
+    #pragma omp parallel for
+    for (uint32_t i=0; i<nToInsert; i++) {
+      nodeInfo[i].hilbertDist = vertices[nodeInfo[i].node].padding.hilbertDist;
+    }
+
+    for (unsigned i=firstPassEver; i<npasses; i++) {
+      HXT_CHECK( hxtNodeInfoSort(nodeInfo+passes[i], passes[i+1]-passes[i]) );
+    }
+
+    if(!noReordering) {
+      double* sizesToInsert = options->nodalSizes + firstToInsert;
 
       size_t vertSize = nToInsert*sizeof(HXTVertex);
       size_t sizeSize = nToInsert*sizeof(double);
@@ -1319,12 +1406,12 @@ static HXTStatus parallelDelaunay3D(HXTMesh* mesh,
       double* sizeCopy;
       HXT_CHECK( hxtAlignedMalloc(&vertCopy, vertSize) );
       HXT_CHECK( hxtAlignedMalloc(&sizeCopy, sizeSize) );
-      
+
       #pragma omp parallel for simd aligned(vertCopy,sizeCopy,nodeInfo: SIMD_ALIGN)
       for (uint32_t i=0; i<nToInsert; i++) {
-        vertCopy[i] = verticesToInsert[nodeInfo[i].node-nodalMin];
-        sizeCopy[i] = sizesToInsert[nodeInfo[i].node-nodalMin];
-        nodeInfo[i].node = nodalMin + i;
+        vertCopy[i] = verticesToInsert[nodeInfo[i].node-firstToInsert];
+        sizeCopy[i] = sizesToInsert[nodeInfo[i].node-firstToInsert];
+        nodeInfo[i].node = firstToInsert + i;
       }
 
       memcpy(verticesToInsert, vertCopy, vertSize);
@@ -1335,6 +1422,7 @@ static HXTStatus parallelDelaunay3D(HXTMesh* mesh,
     }
   }
 
+
   /******************************************************
         Initializations and allocations
   ******************************************************/
@@ -1356,90 +1444,140 @@ static HXTStatus parallelDelaunay3D(HXTMesh* mesh,
 
   TetLocal* Locals;
   HXT_CHECK( hxtMalloc(&Locals, maxThreads*sizeof(TetLocal)) );
-  // HXT_CHECK( hxtMalloc())
+
+  uint64_t* startTetGlobal;
+  HXT_CHECK( hxtMalloc(&startTetGlobal, maxThreads*maxThreads*sizeof(uint64_t)) );
 
   for (int i=0; i<maxThreads; i++)
     localInit(&Locals[i]);
 
-
   HXT_INFO_COND(options->verbosity>0,
-                "Delaunay of %10u vertices on %3d threads\t- mesh.nvert: %-10u",
+                "Delaunay of %10u points on %3d threads - mesh.nvert: %-10u",
                 passes[npasses] - passes[0], maxThreads, options->numVerticesInMesh);
 
-  for (uint32_t p=0; p<npasses; p++)
+  for (uint32_t ipass=0; ipass<npasses; ipass++)
   {
+    int nthreads = maxThreads;
+    double conflictRatio = 0.0;
 
-    double percent = 200;
-    int nthreads = 1;
+    for(uint32_t iround=0; passes[ipass+1]-passes[ipass]; iround++)
     {
-      uint32_t tmp = (passes[p+1]-passes[p])/SMALLEST_ROUND;
-      while(tmp>0 && nthreads<maxThreads){
-        tmp = tmp/2;
-        nthreads*=2;
-      }
-    }
-    nthreads = MIN(nthreads, maxThreads);
-
-    // const uint32_t initialPassLength = passes[p+1] - passes[p];
-
-    for(uint32_t n=0; passes[p+1]-passes[p]; n++)
-    {
-      const uint32_t passStart = passes[p];
-      const uint32_t passEnd = passes[p+1];
+      const uint32_t passStart = passes[ipass];
+      const uint32_t passEnd = passes[ipass+1];
       const uint32_t passLength = passEnd - passStart;
-      double step = (double) passLength/nthreads;
-      double indexShift = 0.0;
+      uint32_t startShift = 0;
+
+      nthreads = computeNumberOfThreads(conflictRatio, nthreads, passes[ipass+1]-passes[ipass], SMALLEST_PASS);
 
       /******************************************************
-                      choosing number of threads
+                      Sorting vertices
       ******************************************************/
-      if(maxThreads>1 || noReordering) {
-        if(percent<140/nthreads || passLength<SMALLEST_ROUND){
-          nthreads=1;
+      if(iround>0 && !(nthreads==1 && defaultMooreCurve)) {
+        double bboxShift[3];
+        if(nthreads==1) {
+          startShift = 0;
+          bboxShift[0] = 0.5;
+          bboxShift[1] = 0.5;
+          bboxShift[2] = 0.5;
+          defaultMooreCurve = 1;
         }
-        else if(percent<20){
-          nthreads=(nthreads+1)/2;
-        }
-        else if(passLength < (uint32_t) nthreads*SMALLEST_ROUND)
-          nthreads=(nthreads+1)/2;
-
-
-        /******************************************************
-                        Sorting vertices
-        ******************************************************/
-        double hxtDeclareAligned bboxShift[4]={0.5,0.5,0.5,0};
-        if(percent<100 && nthreads>1)
-        {
+        else {
+          startShift = (double) hxtReproducibleLCG(&seed)/RAND_MAX;
           bboxShift[0] = (double) hxtReproducibleLCG(&seed)/RAND_MAX;
           bboxShift[1] = (double) hxtReproducibleLCG(&seed)/RAND_MAX;
           bboxShift[2] = (double) hxtReproducibleLCG(&seed)/RAND_MAX;
-          bboxShift[3] = (double) hxtReproducibleLCG(&seed)/RAND_MAX; // this is not a bbox deformation, it's an index shift
+          defaultMooreCurve = 0;
         }
 
-        step = (double) passLength/nthreads;
-        indexShift = bboxShift[3];
-        
         if(noReordering) {
           HXT_CHECK( hxtMoore(options->bbox, vertices, mesh->vertices.num, bboxShift) );
         }
         else {
           HXT_CHECK( hxtMoore(options->bbox, vertices, mesh->vertices.num - nToInsert + passEnd, bboxShift) );
         }
-        
+
         #pragma omp parallel for simd aligned(nodeInfo:SIMD_ALIGN)
         for (uint32_t i=passStart; i<passEnd; i++) {
           nodeInfo[i].hilbertDist = vertices[nodeInfo[i].node].padding.hilbertDist;
         }
 
-        if(p!=0 || n!=0 || nthreads>1 || options->numVerticesInMesh >= SMALLEST_ROUND){
-          HXT_CHECK( hxtNodeInfoSort(nodeInfo + passStart, passLength) );
+        HXT_CHECK( hxtNodeInfoSort(nodeInfo + passStart, passLength) );
+      }
+      else if(!defaultMooreCurve) {
+        if(noReordering) {
+          HXT_CHECK( hxtMoore(options->bbox, vertices, mesh->vertices.num, NULL) );
+        }
+        else {
+          HXT_CHECK( hxtMoore(options->bbox, vertices, mesh->vertices.num - nToInsert + passEnd, NULL) );
+        }
+        defaultMooreCurve = 1;
+      }
 
-          // if we can only do one partition because all points are in the same cell
-          if(nodeInfo[passStart].hilbertDist==nodeInfo[passStart + passLength-1].hilbertDist)
-            nthreads = 1;
+
+      /******************************************************
+                filtering vertices on the Moore curve
+      ******************************************************/
+      uint32_t mooreSkipped = 0;
+      if(options->nodalSizes!=NULL)
+        mooreSkipped = filterOnMooreCurve(vertices, &nodeInfo[passStart], passLength, options->nodalSizes);
+
+
+      /******************************************************
+                        Making partitions
+       ******************************************************/
+      if(nthreads > 1) {
+        uint32_t numToProcessPerThread = (passLength - mooreSkipped) / nthreads + 1;
+        uint32_t counter = numToProcessPerThread;
+        int threadID = 0;
+
+        for(uint32_t i=0; i<passLength; i++) {
+          uint32_t index = (startShift*passLength/nthreads + i) % passLength;
+          uint64_t hilbertDist = nodeInfo[passStart + index].hilbertDist;
+          if(counter>=numToProcessPerThread) {
+            uint64_t prevDist = nodeInfo[passStart + (index + passLength - 1) % passLength].hilbertDist;
+            // uint64_t nextDist = nodeInfo[passStart + (index + 1) % passLength].hilbertDist;
+            // uint64_t prevGrad = hilbertDist - prevDist;
+            // uint64_t nextGrad = nextDist - hilbertDist;
+
+            if(/*nextGrad <= prevGrad &&*/ hilbertDist!=prevDist) {
+              Locals[threadID].partition.firstElem = index;
+              Locals[threadID].partition.startDist = prevDist + (hilbertDist - prevDist + 1)/2;
+              counter = 0;
+              threadID++;
+            }
+          }
+
+          if(nodeInfo[passStart + index].status==HXT_STATUS_TRYAGAIN)
+            counter++;
+        }
+
+        if(threadID <= 1) {
+          nthreads = 1;
+        }
+        else {
+          nthreads = threadID;
+
+          // don't forget to fill all the fields of partitions
+          for(threadID=0; threadID<nthreads; threadID++) {
+            uint32_t localStart = Locals[threadID].partition.firstElem;
+            uint32_t localEnd = Locals[(threadID+1)%nthreads].partition.firstElem;
+            Locals[threadID].partition.numElem = (localEnd + passLength - localStart)%passLength;
+
+            Locals[threadID].partition.lengthDist = Locals[(threadID+1)%nthreads].partition.startDist
+                                                  - Locals[threadID].partition.startDist;
+          }
         }
       }
 
+
+      if(nthreads==1) {
+        Locals[0].partition.startDist = 0;
+        Locals[0].partition.lengthDist = UINT64_MAX;
+        Locals[0].partition.firstElem = 0;
+        Locals[0].partition.numElem = passLength;
+      }
+
+
       HXT2Sync shared2sync = {.mesh = mesh,
                               .allocMore = 8,
                               .otherArrays = {NULL},
@@ -1447,6 +1585,58 @@ static HXTStatus parallelDelaunay3D(HXTMesh* mesh,
                               .otherArraysSetDeleted = {NULL},
                               .threadFinished = 0};
 
+      if(nthreads>1){
+        if(options->reproducible){
+
+          #pragma omp parallel num_threads(maxThreads)
+          {
+            int threadID = omp_get_thread_num();
+            // we want to reorder tets only at the very end. Because the selected tet should not depend
+            // on the ordering of tet in reproducible mode, we have very few options...
+            // we will select the tet in the good partition that has the lowest nodes in lexicographic order
+            uint64_t* startTetLocal = startTetGlobal + threadID * nthreads;
+            for(int i=0; i<nthreads; i++) {
+              startTetLocal[i] = UINT64_MAX;
+            }
+
+            #pragma omp for
+            for (uint64_t i=0; i<mesh->tetrahedra.num; i++)
+            {
+              if(getDeletedFlag(mesh, i)==0)
+              {
+                int partitionOfTet = -1;
+                for(int t=0; t<nthreads; t++) {
+                  if(checkTetrahedron(vertices,
+                                      &Locals[t].partition,
+                                      &mesh->tetrahedra.node[i*4]
+                                      )==HXT_STATUS_OK) {
+                    partitionOfTet = t;
+                    break;
+                  }
+                }
+
+                if(partitionOfTet==-1)
+                  continue;
+
+                uint64_t oldStartTet = startTetLocal[partitionOfTet];
+
+                if(oldStartTet==UINT64_MAX) {
+                  startTetLocal[partitionOfTet] = i;
+                }
+                else {
+                  int cmp = compareNodeLexicographically(&mesh->tetrahedra.node[4*i],
+                                                         &mesh->tetrahedra.node[4*oldStartTet]);
+                  HXT_ASSERT(cmp!=0);
+                  if(cmp==-1){
+                    startTetLocal[partitionOfTet] = i;
+                  }
+                }
+              }
+            } // implicit barrier at the end of the omp for loop :-)
+          }
+        }
+      }
+
       #pragma omp parallel num_threads(nthreads)
       {
       #ifdef _MSC_VER
@@ -1454,80 +1644,30 @@ static HXTStatus parallelDelaunay3D(HXTMesh* mesh,
         nthreads = omp_get_num_threads();
       #endif
 
-        uint64_t curTet = 0; // we always begin with the first tet. (index 0)
+        uint64_t curTet = HXT_NO_ADJACENT;
         const int threadID = omp_get_thread_num();
 
-        uint32_t localStart;
-        uint32_t localN;
-        int foundTet = 0;
+        uint32_t localStart = Locals[threadID].partition.firstElem;
+        uint32_t localN = Locals[threadID].partition.numElem;
 
         if(nthreads>1){
-          // if(threadID<nthreads){
-
-          /******************************************************
-                          Making partitions
-          ******************************************************/
-          localStart = MIN((uint32_t) step*(threadID+1)-1, (uint32_t) (step*(threadID + indexShift)));
-          uint64_t dist = nodeInfo[passStart + localStart].hilbertDist;
-          
-          uint32_t up = 1;
-          while(localStart+up<passLength && dist==nodeInfo[passStart + localStart + up].hilbertDist)
-            up++;
-
-          localStart = localStart+up==passLength?0:localStart+up;
-          if(localStart > 0) {
-            dist = (nodeInfo[passStart + localStart].hilbertDist
-                   + nodeInfo[passStart + localStart - 1].hilbertDist + 1)/2;
-          }
-          else {
-            dist = nodeInfo[passStart + passLength-1].hilbertDist
-                   + (nodeInfo[passStart + localStart].hilbertDist
-                   - nodeInfo[passStart + passLength - 1].hilbertDist)/2;
-          }
-          Locals[threadID].partition.startDist = dist;
-          Locals[threadID].partition.firstElem = localStart;
-          // }
-
-          #pragma omp barrier
-
-          // if(threadID<nthreads){
-          uint32_t localEnd = Locals[(threadID+1)%nthreads].partition.firstElem;
-          localN = (localEnd + passLength - localStart)%passLength;
-          Locals[threadID].partition.numElem = localN;
-
-          Locals[threadID].partition.lengthDist = Locals[(threadID+1)%nthreads].partition.startDist - dist;
-
 
           /******************************************************
                           find starting tetrahedron
           ******************************************************/
-          // we want to reorder tets only at the very end. Because the selected tet should not depend
-          // on the ordering of tet in reproducible mode, we have very few options...
-          // we will select the tet in the good partition that has the lowest nodes in lexicographic order
           if(options->reproducible){
-
-            for (uint64_t i=0; i<mesh->tetrahedra.num; i++)
-            {
-              if(getDeletedFlag(mesh, i)==0 &&
-                 checkTetrahedron(vertices, &Locals[threadID],
-                                  mesh->tetrahedra.node + i*4 )==HXT_STATUS_OK)
-              {
-                if(foundTet==0) {
-                  curTet = i;
-                  foundTet = 1;
+            for(int t=0; t<maxThreads; t++) {
+              uint64_t startTet = startTetGlobal[t*nthreads + threadID];
+              if(startTet != UINT64_MAX) {
+                if(curTet==HXT_NO_ADJACENT) {
+                  curTet = startTet;
                 }
                 else {
-                  uint32_t* iNode = &mesh->tetrahedra.node[4*i];
-                  uint32_t* curNode = &mesh->tetrahedra.node[4*curTet];
-
-                  // compare in lexicographic order
-                  for(int j=0; j<4; j++) {
-                    if(iNode[j]<curNode[j]){
-                      curTet = i;
-                      break;
-                    }
-                    if(iNode[j]>curNode[j])
-                      break;
+                  int cmp = compareNodeLexicographically(&mesh->tetrahedra.node[4*startTet],
+                                                         &mesh->tetrahedra.node[4*curTet]);
+                  HXT_ASSERT(cmp!=0);
+                  if(cmp==-1){
+                    curTet = startTet;
                   }
                 }
               }
@@ -1538,75 +1678,35 @@ static HXTStatus parallelDelaunay3D(HXTMesh* mesh,
             for (uint64_t i=0; i<mesh->tetrahedra.num; i++)
             {
               if(getDeletedFlag(mesh, i)==0 &&
-                 checkTetrahedron(vertices, &Locals[threadID],
+                 checkTetrahedron(vertices, &Locals[threadID].partition,
                                   mesh->tetrahedra.node + i*4 )==HXT_STATUS_OK)
               {
                 curTet = i;
-                foundTet = 1;
                 break;
               }
             }
           }
-
-          // }
-
-          #pragma omp barrier
         }
-        else
-          // if(threadID==0)
-        {
-
+        else {
           /******************************************************
-             single-thread partition and starting tetrahedron
+             single-thread starting tetrahedron
           ******************************************************/
-          localStart = 0;
-          localN = passLength;
-          Locals[0].partition.startDist = 0;
-          Locals[0].partition.lengthDist = UINT64_MAX;
-
           for (uint64_t i=0; i<mesh->tetrahedra.num; i++)
-          { 
+          {
             if(getDeletedFlag(mesh, i)==0){
               curTet = i;
-              foundTet = 1;
               break;
             }
           }
         }
 
-        if (foundTet == 0) {
+        #pragma omp barrier
+
+        if (curTet==HXT_NO_ADJACENT) {
           HXT_INFO_COND(options->verbosity>1,
                         "thread %d did not find any tetrahedron to begin with", threadID);
         }
-
-        // filtering vertices on the Moore curve
-        if(options->nodalSizes!=NULL)
-        {
-          double* p1 = NULL;
-          double p1Size = 0;
-
-          for (uint32_t i=0; i<localN; i++)
-          {
-            uint32_t passIndex = (localStart+i)%passLength;
-            uint32_t lastNode = nodeInfo[passStart + passIndex].node;
-            if(nodeInfo[passStart + passIndex].status==HXT_STATUS_TRYAGAIN){
-              double* p2 = vertices[lastNode].coord;
-              double p2Size = options->nodalSizes[lastNode];
-              if(p1!=NULL && pointIsTooClose(p1, p2, 0.5*(p1Size+p2Size))!=HXT_STATUS_OK){
-                nodeInfo[passStart + passIndex].status=HXT_STATUS_FALSE;
-              }
-              else{
-                p1 = p2;
-                p1Size = p2Size;
-              }
-            }
-          }
-        }
-
-
-        // if(threadID<nthreads){
-        if(foundTet!=0){
-
+        else{
           /******************************************************
                           vertices insertion
           ******************************************************/
@@ -1627,7 +1727,7 @@ static HXTStatus parallelDelaunay3D(HXTMesh* mesh,
                 case HXT_STATUS_DOUBLE_PT:
                   nodeInfo[passStart + passIndex].status = HXT_STATUS_FALSE;
                   double* vtaCoord = vertices[vta].coord;
-                  HXT_WARNING("skipping supposedly duplicate vertex (%f %f %f)", vtaCoord[0], vtaCoord[1], vtaCoord[2]);
+                  HXT_WARNING("skipping supposedly duplicate point (%f %f %f)", vtaCoord[0], vtaCoord[1], vtaCoord[2]);
                   break;
                 case HXT_STATUS_CONFLICT:
                   status = HXT_STATUS_TRYAGAIN;
@@ -1647,7 +1747,6 @@ static HXTStatus parallelDelaunay3D(HXTMesh* mesh,
             }
           }
         }
-        // }
 
         HXT_OMP_CHECK( waitForPossibleReallocation(&shared2sync, nthreads) );
       }
@@ -1657,7 +1756,7 @@ static HXTStatus parallelDelaunay3D(HXTMesh* mesh,
       ******************************************************/
       // everything above i+shift is HXT_STATUS_TRYAGAIN
       uint32_t shift = 0;
-      unsigned numSkipped = 0;
+      uint32_t numSkipped = 0;
       for (uint32_t i=passEnd; i>passStart;)
       {
         i--;
@@ -1673,19 +1772,51 @@ static HXTStatus parallelDelaunay3D(HXTMesh* mesh,
         }
       }
 
-      options->numVerticesInMesh += shift - numSkipped;
+      uint32_t numInserted = shift - numSkipped;
+      uint32_t numConflict = passLength - shift;
 
-      percent = (shift-numSkipped)*100.0/MAX(1,passLength-numSkipped);
+      totalNumInserted += numInserted;
       totalNumSkipped += numSkipped;
 
-      HXT_INFO_COND(options->verbosity>1,
-                    "%3d thrd |%10u/%-10u-> %*.1f%-*c\t- mesh.nvert: %-10u",
-                    nthreads, shift-numSkipped, passLength-numSkipped, MIN(8,n/2)+5, percent, 8-MIN(8,n/2),'%', options->numVerticesInMesh);
+      conflictRatio = (double) numConflict / (passLength - numSkipped);
+
+      if(options->verbosity>1) {
+          uint32_t numPointsMinusSkipped = passLength - numSkipped;
+          uint32_t numInserted = numPointsMinusSkipped - numConflict;
+          int numSpaces = MIN(8, iround/2)+5;
+          HXT_INFO("%3d thrd |%10u/%-10u-> %*.1f%%",
+                   nthreads, numInserted, numPointsMinusSkipped,
+                   numSpaces, 100.0*MAX((double) numInserted/numPointsMinusSkipped, 0.0));
+      }
+
+      // printf("moore filtered %4.1f%%\n", mooreSkipped*100.0/passLength);
+      // printf("total filtered %4.1f%%\n", numSkipped*100.0/passLength);
+      // printf("      conflict %4.1f%%\n", numConflict*100.0/passLength);
+      // printf("      inserted %4.1f%%\n", numInserted*100.0/passLength);
+      // printf("filtered/inserted %f\n", (numSkipped - mooreSkipped)*1.0/numInserted);
       
-      passes[p] += shift;
+      passes[ipass] += shift;
+
+      // compute if there was a nonDeterministic ordering of allocation
+      if(options->reproducible && nonDeterministic==0) {
+        int createdNew = 0;
+        for(int threadID=0; threadID<nthreads; threadID++) {
+          if(Locals[threadID].deleted.createdNew)
+            createdNew++;
+        }
+
+        if(createdNew>1)
+          nonDeterministic = 1;
+      }
+
+      for(int threadID=0; threadID<maxThreads; threadID++) {
+        Locals[threadID].deleted.createdNew = 0;
+      }
     }
   }
 
+  options->numVerticesInMesh += totalNumInserted;
+
   /******************************************************
                   Cleaning
   ******************************************************/
@@ -1707,6 +1838,7 @@ static HXTStatus parallelDelaunay3D(HXTMesh* mesh,
 
   HXT_CHECK( hxtAlignedFree(&verticesID) );
   HXT_CHECK( hxtFree(&Locals) );
+  HXT_CHECK( hxtFree(&startTetGlobal) );
 
   /***************************************************************
     if reordering allowed, remove vertices we could not insert
@@ -1786,23 +1918,22 @@ static HXTStatus parallelDelaunay3D(HXTMesh* mesh,
       vertices[vertices[i].padding.index] = vertices[i];
     }
 
-    if(options->verbosity>1)
-      HXT_INFO("%u vertices removed (vertices not inserted in the mesh are removed when using hxtDelaunay)", totalNumSkipped);
-
     mesh->vertices.num = mesh->vertices.num - totalNumSkipped;
   }
 
-  HXT_INFO_COND(options->verbosity>0, "Delaunay done !%10u skipped", totalNumSkipped);
-  HXT_INFO_COND(options->verbosity>1, "mem. allocated:%5.2fGB - mesh.ntet: %-12lu - mesh.nvert: %-10lu",
-    ((50 + 2*(mesh->tetrahedra.flag!=NULL)) * mesh->tetrahedra.size +
-     (32 + 8*(options->nodalSizes!=NULL)) * mesh->vertices.size)/(1024.*1024.*1024.),
-    mesh->tetrahedra.num, mesh->vertices.num);
+  if(totalNumSkipped!=0 && options->verbosity>0) {
+    HXT_INFO("          - %10u points filtered", totalNumSkipped);
+    HXT_INFO("          = %10u points added", totalNumInserted);
+    HXT_INFO_COND(options->verbosity>1, "mem. allocated:%5.2fGB - mesh.ntet: %-9lu- mesh.nvert: %-10lu",
+      ((50 + 2*(mesh->tetrahedra.flag!=NULL)) * mesh->tetrahedra.size +
+       (32 + 8*(options->nodalSizes!=NULL)) * mesh->vertices.size)/(1024.*1024.*1024.),
+      mesh->tetrahedra.num, mesh->vertices.num);
+  }
 
-  if(options->reproducible && maxThreads!=1){
+  if(nonDeterministic){
     HXT_INFO_COND(options->verbosity>1, "Reordering tetrahedra (reproducible==true)", mesh->vertices.num - nToInsert, mesh->vertices.num);
     HXT_CHECK( hxtTetReorder(mesh) );
   }
-  HXT_INFO_COND(options->verbosity>1,""); // just separate stuff with a blank line
 
   return HXT_STATUS_OK;
 }
@@ -1900,13 +2031,6 @@ HXTStatus hxtDelaunay(HXTMesh* mesh, HXTDelaunayOptions* userOptions){
 
   hxtNodeInfo* nodeInfo;
   HXT_CHECK( hxtAlignedMalloc(&nodeInfo, nToInsert*sizeof(hxtNodeInfo)) );
-  
-  // we fill nodeInfo with the indices of each vertices to insert...
-  #pragma omp parallel for simd
-  for (uint32_t i=0; i<nToInsert; i++) {
-    nodeInfo[i].node = options.numVerticesInMesh + i;
-    nodeInfo[i].status = HXT_STATUS_TRYAGAIN; // necessary for when foundTet = 0;
-  }
 
   HXT_CHECK( parallelDelaunay3D(mesh, &options, nodeInfo, nToInsert, 0) );
 
diff --git a/contrib/hxt/hxt_tetDelaunay.h b/contrib/hxt/tetMesh/src/hxt_tetDelaunay.h
similarity index 94%
rename from contrib/hxt/hxt_tetDelaunay.h
rename to contrib/hxt/tetMesh/src/hxt_tetDelaunay.h
index 7a3edab07f..885cc79d0e 100644
--- a/contrib/hxt/hxt_tetDelaunay.h
+++ b/contrib/hxt/tetMesh/src/hxt_tetDelaunay.h
@@ -1,5 +1,13 @@
-#ifndef _HXT_TETDELAUNAY_
-#define _HXT_TETDELAUNAY_
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
+#ifndef HXT_TETDELAUNAY_H
+#define HXT_TETDELAUNAY_H
 
 #ifdef __cplusplus
 extern "C" {
@@ -35,6 +43,8 @@ typedef struct {
                                * doesn't have a corresponding mesh size */
 
   uint32_t numVerticesInMesh; /**< The number of vertices in the mesh (all vertices below this point are not (re-)inserted */
+  double partitionability;    /**< a number between 0 and 1 telling if this mesh is good for making partitions.
+                                   Generally, put 0 for an empty mesh, 1-(1/2)^n for a mesh refined n time */
 
   int verbosity;              /**<
                                *  - if verbosity<=0: don't print information.
diff --git a/contrib/hxt/hxt_tetFlag.c b/contrib/hxt/tetMesh/src/hxt_tetFlag.c
similarity index 98%
rename from contrib/hxt/hxt_tetFlag.c
rename to contrib/hxt/tetMesh/src/hxt_tetFlag.c
index 6e0f47e006..5172c1c93f 100644
--- a/contrib/hxt/hxt_tetFlag.c
+++ b/contrib/hxt/tetMesh/src/hxt_tetFlag.c
@@ -1,3 +1,11 @@
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
 #include "hxt_sort.h"
 #include "hxt_tetFlag.h"
 
@@ -335,7 +343,7 @@ HXT_ASSERT( mesh!=NULL );
         #ifndef NDEBUG
           if(edgeKey[i+1].v[1]%2==0) {
             HXT_ERROR_MSG(HXT_STATUS_ERROR, "Duplicated line in mesh->lines (" HXTu64 " & " HXTu64 ")\n"
-                                           "\tThis case is not handled in Release mode, FIX IT !!",
+                                            "\tThis issue will not produce a direct error if NDEBUG is defined",
                                            edgeKey[i].v[1]/2, edgeKey[i+1].v[1]/2);
             exit(EXIT_FAILURE);
           }
diff --git a/contrib/hxt/hxt_tetFlag.h b/contrib/hxt/tetMesh/src/hxt_tetFlag.h
similarity index 97%
rename from contrib/hxt/hxt_tetFlag.h
rename to contrib/hxt/tetMesh/src/hxt_tetFlag.h
index 7ff7db77c3..b93bd1e94c 100644
--- a/contrib/hxt/hxt_tetFlag.h
+++ b/contrib/hxt/tetMesh/src/hxt_tetFlag.h
@@ -1,5 +1,13 @@
-#ifndef _HXT_TETFLAG_
-#define _HXT_TETFLAG_
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
+#ifndef HXT_TETFLAG_H
+#define HXT_TETFLAG_H
 
 #ifdef __cplusplus
 extern "C" {
@@ -163,10 +171,12 @@ HXTStatus hxtConstrainLinesNotInTriangles(HXTMesh* mesh, uint64_t* lines2TetMap,
 
 #define HXT_DELETED_MASK UINT16_C(0x40)
 #define HXT_PROCESSED_MASK UINT16_C(0X80)
+
 #define HXT_UNUSED0_MASK UINT16_C(0x1000)
 #define HXT_UNUSED1_MASK UINT16_C(0x2000)
 #define HXT_UNUSED2_MASK UINT16_C(0x4000)
 #define HXT_UNUSED3_MASK UINT16_C(0x8000)
+#define HXT_ALL_UNUSED_MASK UINT16_C(0xF000)
 
 
 /***************************
@@ -346,6 +356,11 @@ static inline void unsetUnusedFlag(HXTMesh* mesh, uint64_t tet, unsigned id) {
 }
 
 
+static inline void resetUnusedFlags(HXTMesh* mesh, uint64_t tet) {
+  mesh->tetrahedra.flag[tet] &= ~UINT16_C(HXT_ALL_UNUSED_MASK);
+}
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/contrib/hxt/hxt_tetMesh.c b/contrib/hxt/tetMesh/src/hxt_tetMesh.c
similarity index 86%
rename from contrib/hxt/hxt_tetMesh.c
rename to contrib/hxt/tetMesh/src/hxt_tetMesh.c
index b63fa0aeb3..0dfd49fcde 100644
--- a/contrib/hxt/hxt_tetMesh.c
+++ b/contrib/hxt/tetMesh/src/hxt_tetMesh.c
@@ -1,3 +1,11 @@
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
 #include "hxt_tetRefine.h"
 #include "hxt_tetNodalSize.h"
 #include "hxt_tetRepair.h"
@@ -8,6 +16,8 @@
 
 #include "hxt_tetMesh.h"
 #include "hxt_tetQuality.h"
+#include "hxt_omp.h"
+
 // void aspect_ratio_graph(HXTMesh* mesh) {
 //     // make a count of aspect ratio...
 //   unsigned bins[21] = {0};
@@ -60,6 +70,7 @@ HXTStatus hxtTetMesh(HXTMesh* mesh,
   
   HXT_INFO_COND(options->verbosity>0, "Creating an empty mesh with %u vertices", numVerticesConstrained);
   HXT_CHECK( hxtEmptyMesh(mesh, &delOptions) );
+  HXT_INFO_COND(options->verbosity>1, "Empty mesh finished\n");
 
   t[1] = omp_get_wtime();
 
@@ -91,10 +102,10 @@ HXTStatus hxtTetMesh(HXTMesh* mesh,
         "there are missing features but no boundary recovery function is given");
 
     if(nbMissingTriangles)
-      HXT_INFO("Recovering " HXTu64 " missing facet(s)",
+      HXT_INFO("Recovering %" HXTu64 " missing facet(s)",
                nbMissingTriangles);
     else if(nbMissingLines)
-      HXT_INFO("Recovering " HXTu64 " missing edge(s)",
+      HXT_INFO("Recovering %" HXTu64 " missing edge(s)",
                nbMissingLines);
 
     HXT_CHECK(options->recoveryFun(mesh, options->recoveryData));
@@ -109,7 +120,7 @@ HXTStatus hxtTetMesh(HXTMesh* mesh,
     HXT_CHECK( hxtGetTri2TetMap(mesh, tri2TetMap, &nbMissingTriangles) );
     if(nbMissingTriangles!=0)
       return HXT_ERROR_MSG( HXT_STATUS_ERROR,
-        HXTu64 " boundary face%s still missing (after recovery step).",
+        "%" HXTu64 " boundary face%s still missing (after recovery step).",
         nbMissingTriangles, (nbMissingTriangles>1)?"s are":" is" );
 
     if(nbLinesNotInTriangles!=0)
@@ -117,8 +128,10 @@ HXTStatus hxtTetMesh(HXTMesh* mesh,
 
     if(nbMissingLines!=0)
       return HXT_ERROR_MSG( HXT_STATUS_ERROR,
-        HXTu64 " constrained edge%s still missing (after recovery step).",
+        "%" HXTu64 " constrained edge%s still missing (after recovery step).",
         nbMissingLines, (nbMissingLines>1)?"s are":" is" );
+
+    HXT_INFO_COND(options->verbosity>1,"Constrained lines and triangles recovered\n");
   }
 
   HXT_CHECK( hxtConstrainTriangles(mesh, tri2TetMap) );
@@ -148,6 +161,8 @@ HXTStatus hxtTetMesh(HXTMesh* mesh,
     HXT_CHECK(hxtRefineTetrahedra(mesh, &delOptions, options->meshSizeFun, options->meshSizeData));
 
     HXT_CHECK( hxtDestroyNodalsize(&delOptions.nodalSizes) );
+
+    HXT_INFO_COND(options->verbosity>1, "Mesh refinement finished\n");
   }
 
   t[5] = omp_get_wtime();
@@ -165,8 +180,10 @@ HXTStatus hxtTetMesh(HXTMesh* mesh,
                                        .qualityMin = options->qualityMin,
                                        .numThreads = options->improveThreads,
                                        .numVerticesConstrained = numVerticesConstrained,
-                                       .verbosity = options->verbosity
+                                       .verbosity = options->verbosity,
+                                       .reproducible = options->reproducible
                                      } ) );
+    HXT_INFO_COND(options->verbosity>1, "Mesh improvement finished\n");
   }
 
   // aspect_ratio_graph(mesh);
@@ -174,11 +191,8 @@ HXTStatus hxtTetMesh(HXTMesh* mesh,
 
   
   if(options->stat){
-    HXT_INFO("\n\t\tFinal tet. mesh contains " HXTu64 " tetrahedra"
-             "\n\t\tand                      %u vertices",
-             mesh->tetrahedra.num,
-             mesh->vertices.num);
-
+    HXT_INFO(" \tFinal tet. mesh contains %" HXTu64 " tetrahedra", mesh->tetrahedra.num);
+    HXT_INFO(" \tFinal tet. mesh contains %u vertices", mesh->vertices.num);
     HXT_INFO("tEmptyMesh  \t = \t %8.3f", t[1]-t[0]);
     HXT_INFO("tVerifyBnd  \t = \t %8.3f", t[2]-t[1]);
     if(t[3]){
@@ -200,6 +214,8 @@ HXTStatus hxtTetMesh(HXTMesh* mesh,
       HXT_INFO("tOptimize   \t = \t    0.000 (mesh optimization disabled)");
   }
 
+  HXT_INFO_COND(options->verbosity>1, "Mesh generated\n");
+
   return HXT_STATUS_OK;
 }
 
diff --git a/contrib/hxt/hxt_tetNodalSize.c b/contrib/hxt/tetMesh/src/hxt_tetNodalSize.c
similarity index 96%
rename from contrib/hxt/hxt_tetNodalSize.c
rename to contrib/hxt/tetMesh/src/hxt_tetNodalSize.c
index fd9b51112d..7150bd0e3a 100644
--- a/contrib/hxt/hxt_tetNodalSize.c
+++ b/contrib/hxt/tetMesh/src/hxt_tetNodalSize.c
@@ -1,4 +1,13 @@
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
 #include "hxt_vertices.h"
+#include <math.h>
 
 
 HXTStatus hxtCreateNodalSizeFromFunction(HXTMesh* mesh, double** nodalSizes_ptr,
diff --git a/contrib/hxt/hxt_tetNodalSize.h b/contrib/hxt/tetMesh/src/hxt_tetNodalSize.h
similarity index 76%
rename from contrib/hxt/hxt_tetNodalSize.h
rename to contrib/hxt/tetMesh/src/hxt_tetNodalSize.h
index 5af1c668cc..c1d10d2d9f 100644
--- a/contrib/hxt/hxt_tetNodalSize.h
+++ b/contrib/hxt/tetMesh/src/hxt_tetNodalSize.h
@@ -1,5 +1,13 @@
-#ifndef _HXT_TETNODALSIZE_
-#define _HXT_TETNODALSIZE_
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
+#ifndef HXT_TETNODALSIZE_H
+#define HXT_TETNODALSIZE_H
 
 #include "hxt_mesh.h"
 
diff --git a/contrib/hxt/tetMesh/src/hxt_tetOpti.c b/contrib/hxt/tetMesh/src/hxt_tetOpti.c
new file mode 100644
index 0000000000..add322fafc
--- /dev/null
+++ b/contrib/hxt/tetMesh/src/hxt_tetOpti.c
@@ -0,0 +1,724 @@
+// 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_tetFlag.h"
+#include "hxt_edgeRemoval.h"
+#include "hxt_smoothing.h"
+#include "HXTSPR.h"
+#include "hxt_sort.h"
+#include "hxt_tetRepair.h"
+#include "hxt_tetOptiUtils.h"
+
+
+static inline uint16_t getConflictFlag(HXTMesh* mesh, uint64_t tet) {
+  return getUnusedFlag(mesh, tet, 0);
+}
+
+
+static inline void setConflictFlag(HXTMesh* mesh, uint64_t tet) {
+  setUnusedFlag(mesh, tet, 0);
+}
+
+
+static inline void unsetConflictFlag(HXTMesh* mesh, uint64_t tet) {
+  unsetUnusedFlag(mesh, tet, 0);
+}
+
+static void conflictFlagsInit(HXTMesh* mesh, HXTGroup2* badTets, uint64_t num) {
+  #pragma omp parallel for simd
+  for(uint64_t i=0; i<num; i++) {
+    setConflictFlag(mesh, badTets[i].v[1]);
+  }
+}
+
+
+/**************************************************************************
+                    Thread-shared structure
+ **************************************************************************/
+typedef struct {
+  struct {
+    HXTGroup2* array;
+    uint64_t num;
+  } badTets;
+
+  HXTTetDates date;
+  HXTTetQualities quality;
+  HXT2Sync toSync;
+
+  int numThreads;
+} ThreadShared;
+
+
+/**************************************************************************
+  create/update/delete shared structure, containing list of bad tetrahedra
+ **************************************************************************/
+
+// suppose that the right capacity for quality values is already allocated
+static HXTStatus badTets_update(HXTMesh* mesh, ThreadShared* shared) {
+  int maxThreads = omp_get_max_threads();
+  HXTStatus status = HXT_STATUS_OK;
+
+  uint64_t* badTetsCount;
+  HXT_CHECK( hxtMalloc(&badTetsCount, maxThreads*sizeof(uint64_t)) );
+
+  #pragma omp parallel
+  {
+    int threadID = omp_get_thread_num();
+    badTetsCount[threadID] = 0;
+
+    #pragma omp for schedule(static)
+    for (uint64_t i=0; i<mesh->tetrahedra.num; i++) {
+      if(!getProcessedFlag(mesh, i) &&
+         !getDeletedFlag(mesh, i) &&
+         shared->quality.values[i]<shared->quality.threshold)
+        badTetsCount[threadID]++;
+    }
+
+    #pragma omp barrier
+    #pragma omp single
+    {
+      int nthreads = omp_get_num_threads();
+      shared->badTets.num = 0;
+      for (int i=0; i<nthreads; i++) {
+        uint64_t tsum = badTetsCount[i] + shared->badTets.num;
+        badTetsCount[i] = shared->badTets.num;
+        shared->badTets.num = tsum;
+      }
+
+      status = hxtAlignedFree(&shared->badTets.array);
+      if(status==HXT_STATUS_OK)
+        status = hxtAlignedMalloc(&shared->badTets.array, sizeof(HXTGroup2)*shared->badTets.num);
+    }
+
+    if(status==HXT_STATUS_OK){
+      #pragma omp for schedule(static)
+      for (uint64_t i=0; i<mesh->tetrahedra.num; i++) {
+        if(!getProcessedFlag(mesh, i) &&
+           !getDeletedFlag(mesh, i) &&
+           shared->quality.values[i]<shared->quality.threshold){
+          uint64_t badTetsID = badTetsCount[threadID]++;
+          shared->badTets.array[badTetsID].v[1] = i;
+        }
+      }
+    }
+  }
+  HXT_CHECK( hxtFree(&badTetsCount) );
+
+  return status;
+}
+
+
+static HXTStatus badTets_update_among_conflicts(HXTMesh* mesh, ThreadShared* shared) {
+  int maxThreads = omp_get_max_threads();
+  HXTStatus status = HXT_STATUS_OK;
+
+  uint64_t* badTetsCount;
+  HXT_CHECK( hxtMalloc(&badTetsCount, maxThreads*sizeof(uint64_t)) );
+
+  uint64_t oldBadTetNum = shared->badTets.num;
+  HXTGroup2* oldBadTets = shared->badTets.array;
+
+  #pragma omp parallel
+  {
+    int threadID = omp_get_thread_num();
+    badTetsCount[threadID] = 0;
+
+    #pragma omp for schedule(static)
+    for (uint64_t i=0; i<oldBadTetNum; i++) {
+      if(getConflictFlag(mesh, oldBadTets[i].v[1]) && !getDeletedFlag(mesh, oldBadTets[i].v[1]))
+        badTetsCount[threadID]++;
+    }
+
+    #pragma omp barrier
+    #pragma omp single
+    {
+      int nthreads = omp_get_num_threads();
+      shared->badTets.num = 0;
+      for (int i=0; i<nthreads; i++) {
+        uint64_t tsum = badTetsCount[i] + shared->badTets.num;
+        badTetsCount[i] = shared->badTets.num;
+        shared->badTets.num = tsum;
+      }
+
+      status = hxtAlignedMalloc(&shared->badTets.array, sizeof(HXTGroup2)*shared->badTets.num);
+    }
+
+    if(status==HXT_STATUS_OK){
+      #pragma omp for schedule(static)
+      for (uint64_t i=0; i<oldBadTetNum; i++) {
+        if(getConflictFlag(mesh, oldBadTets[i].v[1]) && !getDeletedFlag(mesh, oldBadTets[i].v[1])) {
+          uint64_t badTetsID = badTetsCount[threadID]++;
+          shared->badTets.array[badTetsID] = oldBadTets[i];
+        }
+      }
+    }
+  }
+  HXT_CHECK( hxtFree(&badTetsCount) );
+  HXT_CHECK( hxtAlignedFree(&oldBadTets) );
+
+  return status;
+}
+
+
+static HXTStatus threadShared_init(HXTMesh *mesh,
+                                     HXTOptimizeOptions* options,
+                                     ThreadShared* shared) {
+  shared->numThreads = options->numThreads;
+
+  if(options->qualityMin<0.0)
+    return HXT_ERROR_MSG(HXT_STATUS_ERROR, "quality threshold must be positive");
+
+  shared->badTets.array = NULL;
+  shared->badTets.num = mesh->tetrahedra.num;
+  shared->quality.function = options->qualityFun ? options->qualityFun : hxtTetAspectRatio;
+  shared->quality.threshold = options->qualityMin;
+  shared->quality.userData = options->qualityData;
+  HXT_CHECK( hxtAlignedMalloc(&shared->quality.values, sizeof(double)*mesh->tetrahedra.size) );
+
+  shared->date.current = 0;
+  HXT_CHECK( hxtAlignedMalloc(&shared->date.values, sizeof(HXTTetDate)*mesh->tetrahedra.size) );
+
+  shared->toSync = (HXT2Sync) {.mesh = mesh,
+                               .allocMore = 0,
+                               .otherArrays = {(void*) &shared->quality.values,
+                                               (void*) &shared->date.values, NULL, NULL},
+                               .otherArraysElementSize = {sizeof(double), sizeof(HXTTetDate), 0, 0},
+                               .otherArraysSetDeleted = {NULL, NULL, NULL, NULL},
+                               .threadFinished = 0};
+
+  #pragma omp parallel for
+  for (uint64_t i=0; i<mesh->tetrahedra.num; i++) {
+    shared->date.values[i] = (HXTTetDate) {0};
+
+    if(!getProcessedFlag(mesh, i)) {
+      uint32_t* nodes = mesh->tetrahedra.node + 4*i;
+// #ifndef NDEBUG
+      if(nodes[3]==HXT_GHOST_VERTEX){
+        exit( HXT_ERROR_MSG(HXT_STATUS_ERROR, "ghost tetrahedra should have been set to processed") );
+      }
+// #endif
+      shared->quality.values[i] = tetQuality(mesh, &shared->quality, nodes[0], nodes[1], nodes[2], nodes[3]);
+    }
+  }
+  return HXT_STATUS_OK;
+}
+
+
+static HXTStatus threadShared_destroy(ThreadShared* shared) {
+  HXT_CHECK( hxtAlignedFree(&shared->quality.values) );
+  HXT_CHECK( hxtAlignedFree(&shared->date.values) );
+  HXT_CHECK( hxtAlignedFree(&shared->badTets.array));
+  return HXT_STATUS_OK;
+}
+
+
+static HXTStatus reorderTetIfNeeded(HXTMesh* mesh, ThreadLocal* locals, int nThreads)
+{
+  int createdNew = 0;
+  for(int i=0; i<nThreads; i++) {
+    if(locals[i].deleted.createdNew)
+      createdNew++;
+  }
+
+  if(createdNew > 1) {
+    HXT_INFO("reordering tetrahedra to ensure reproducibility (reproducible==true)");
+    HXT_CHECK( hxtTetReorder(mesh) );
+  }
+
+  for(int i=0; i<nThreads; i++) {
+    locals[i].deleted.createdNew = 0;
+  }
+
+  return HXT_STATUS_OK;
+}
+
+
+
+/**************************************************************************
+  create/update/delete local structure, containing partitions definition
+ **************************************************************************/
+
+static HXTStatus threadLocals_create(ThreadLocal** locals_ptr, ThreadShared* shared, HXTOptimizeOptions* options) {
+  int nthreads = options->numThreads;
+  ThreadLocal* newLocal;
+  HXT_CHECK( hxtMalloc(&newLocal, nthreads*sizeof(ThreadLocal)));
+
+  for (int threadID=0; threadID<nthreads; threadID++) {
+    HXT_CHECK( hxtAlignedMalloc(&newLocal[threadID].deleted.array, sizeof(uint64_t)*DELETED_BUFFER_SIZE) );
+    // init deleted
+    newLocal[threadID].deleted.size = DELETED_BUFFER_SIZE;
+    newLocal[threadID].deleted.num = 0;
+    newLocal[threadID].deleted.createdNew = 0;
+
+    // partition is initialized in threadLocals_update
+
+    // statistics are also initialize in threadLocals_update
+
+    newLocal[threadID].quality = &shared->quality;
+    newLocal[threadID].date = &shared->date;
+    newLocal[threadID].toSync = &shared->toSync;
+    newLocal[threadID].numVerticesConstrained = options->numVerticesConstrained;
+    newLocal[threadID].SPR.dateOfLastCheck = 0;
+    newLocal[threadID].SPR.dateOfLastCreation = 0;
+    newLocal[threadID].SPR.maxSearchNodes = 500;
+  }
+
+  *locals_ptr = newLocal;
+  return HXT_STATUS_OK;
+}
+
+
+static Statistic threadLocals_collectStats(ThreadLocal* locals, int nThreads) {
+      // check the stat to see if we keep the same number of threads and if we move partitions
+  Statistic stat = {0};
+
+  for (int threadID=0; threadID<nThreads; threadID++)
+  {
+    stat.attempt += locals[threadID].stat.attempt;
+    stat.conflict += locals[threadID].stat.conflict;
+    stat.success += locals[threadID].stat.success;
+  }
+  return stat;
+}
+
+
+static HXTStatus threadLocals_update(HXTMesh* mesh, HXTBbox* bbox,
+                                     ThreadShared* shared, ThreadLocal* locals,
+                                     uint32_t* seed,
+                                     int changePartitionCurve,
+                                     int badTetAlreadySorted)
+{
+  const uint64_t bit63 = UINT64_C(1)<<63;
+  #pragma omp parallel for simd
+  for(uint64_t i=0; i<shared->badTets.num; i++) {
+    shared->badTets.array[i].v[0] &= ~bit63;
+  }
+
+
+  HXTVertex* vertices = (HXTVertex*) mesh->vertices.coord;
+  HXTGroup2* badTets = shared->badTets.array;
+
+  double indexShift = (double) hxtReproducibleLCG(seed)/RAND_MAX;
+
+  if(changePartitionCurve) {
+    double hxtDeclareAligned bboxShift[3];
+    bboxShift[0] = (double) hxtReproducibleLCG(seed)/RAND_MAX;
+    bboxShift[1] = (double) hxtReproducibleLCG(seed)/RAND_MAX;
+    bboxShift[2] = (double) hxtReproducibleLCG(seed)/RAND_MAX;
+
+    HXT_CHECK( hxtMoore(bbox, vertices, mesh->vertices.num, bboxShift) );
+  }
+
+  if(changePartitionCurve || !badTetAlreadySorted) {
+    #pragma omp parallel for simd aligned(badTets:SIMD_ALIGN)
+    for (uint64_t i=0; i<shared->badTets.num; i++) {
+      uint64_t curTet = badTets[i].v[1];
+      uint32_t* nodes = &mesh->tetrahedra.node[4*curTet];
+      uint64_t hilbertDist[4];
+      for(int j=0; j<4; j++) {
+        hilbertDist[j] = vertices[nodes[j]].padding.hilbertDist;
+      }
+
+      HXTSORT_4_VALUES_INPLACE(uint64_t, hilbertDist);
+
+      uint64_t minDist = UINT64_MAX;
+      uint64_t middle = 0;
+      for(int j=0; j<4; j++) {
+        if(hilbertDist[(j+1)%4] - hilbertDist[j] < minDist) {
+          minDist = hilbertDist[(j+1)%4] - hilbertDist[j];
+          middle = hilbertDist[j] + minDist/2;
+        }
+      }
+
+      // we are going to sort the four values
+      badTets[i].v[0] = middle;
+    }
+
+    // sort the bad tetrahedrons following their first node hilbert dist
+    HXT_CHECK(  group2_sort_v0(badTets, shared->badTets.num, bit63 - 1) );
+  }
+
+  if(shared->numThreads==1 || badTets[0].v[0]==badTets[shared->badTets.num-1].v[0]) {
+    // only one partition possible, everything is in the same cell !
+    shared->numThreads = 1;
+    locals[0].partition.startDist = 0;
+    locals[0].partition.lengthDist = UINT64_MAX;
+    locals[0].partition.firstElem = 0;
+    locals[0].partition.numElem = shared->badTets.num;
+    locals[0].stat = (Statistic) {0};
+    return HXT_STATUS_OK;
+  }
+
+  if(shared->numThreads > 1) {
+    const double step = shared->badTets.num/shared->numThreads;
+    #pragma omp parallel num_threads(shared->numThreads)
+    {
+      int threadID = omp_get_thread_num();
+      locals[threadID].stat = (Statistic) {0};
+
+      uint64_t first = MIN((uint64_t) step*(threadID+1)-1, (uint64_t) (step*(threadID + indexShift)));
+      uint64_t startDist = badTets[first].v[0];
+
+      uint64_t up = 1;
+      while(first+up<shared->badTets.num && startDist==badTets[first + up].v[0])
+        up++;
+
+      first = first+up==shared->badTets.num?0:first+up;
+      if(first > 0)
+        startDist = (badTets[first].v[0] + badTets[first - 1].v[0] + 1)/2;
+      else
+        startDist = badTets[shared->badTets.num-1].v[0] + 
+                   (badTets[first].v[0] - badTets[shared->badTets.num - 1].v[0])/2;
+
+      locals[threadID].partition.firstElem = first;
+      locals[threadID].partition.startDist = startDist;
+
+      #pragma omp barrier
+
+      uint64_t firstNext = locals[(threadID+1)%shared->numThreads].partition.firstElem;
+      uint64_t endDist = locals[(threadID+1)%shared->numThreads].partition.startDist;
+      uint64_t numElem = (firstNext + shared->badTets.num - first)%shared->badTets.num;
+      locals[threadID].partition.numElem = numElem;
+      locals[threadID].partition.lengthDist = endDist - startDist;
+
+      uint64_t rel = endDist - startDist;
+
+      // dismiss tetrahedron that are in our list but not in our partition
+      for (uint64_t i=0; i<numElem; i++) {
+        uint64_t index = (first + i)%shared->badTets.num;
+        uint64_t curTet = shared->badTets.array[index].v[1];
+
+        uint32_t* nodes = mesh->tetrahedra.node + 4*curTet;
+
+        if(vertexOutOfPartition(vertices, nodes[0], rel, startDist) + 
+           vertexOutOfPartition(vertices, nodes[1], rel, startDist) + 
+           vertexOutOfPartition(vertices, nodes[2], rel, startDist) + 
+           vertexOutOfPartition(vertices, nodes[3], rel, startDist) > 1) {
+          shared->badTets.array[index].v[0] |= bit63;
+          locals[threadID].stat.attempt++;
+          locals[threadID].stat.conflict++;
+        }
+      }
+    }
+  }
+
+  return HXT_STATUS_OK;
+}
+
+
+static HXTStatus threadLocals_destroy(ThreadLocal** local, int nthreads) {
+  for (int threadID=0; threadID<nthreads; threadID++) {
+    HXT_CHECK( hxtAlignedFree(&(*local)[threadID].deleted.array) );
+  }
+
+  HXT_CHECK( hxtFree(local) );
+  return HXT_STATUS_OK;
+}
+
+
+/* once the SPR is done, the current date should be changed to the date of the lastCheck */
+static void SPRDates_update(ThreadShared* shared, ThreadLocal* locals)
+{
+  uint16_t lastCheck = 0;
+  for(int threadID=0; threadID<shared->numThreads; threadID++) {
+    if(locals[threadID].SPR.dateOfLastCheck > lastCheck)
+      lastCheck = locals[threadID].SPR.dateOfLastCheck;
+  }
+
+  shared->date.current = lastCheck;
+
+  for(int threadID=0; threadID<shared->numThreads; threadID++) {
+    locals[threadID].SPR.dateOfLastCheck = lastCheck;
+    locals[threadID].SPR.dateOfLastCreation = lastCheck;
+  }
+}
+
+
+static void badTetrahedraStat(HXTMesh* mesh, double* quality, double threshold,
+                              uint64_t* badTetNum,
+                              double* meanQuality,
+                              double* minQuality)
+{
+  uint64_t good = 0;
+  uint64_t bad = 0;
+  double sum = 0.0;
+  double min = DBL_MAX;
+
+  #pragma omp parallel for reduction(+: good, bad, sum) reduction(min:min)
+  for (uint64_t i=0; i<mesh->tetrahedra.num; i++)
+  {
+    if(getDeletedFlag(mesh, i) || getProcessedFlag(mesh, i))
+      continue;
+
+    sum += quality[i];
+
+    if(quality[i]<threshold)
+      bad++;
+    else
+      good++;
+
+    if(quality[i]<min)
+      min = quality[i];
+  }
+  
+  *badTetNum = bad;
+  *meanQuality = sum / (good + bad);
+  *minQuality = min;
+}
+
+
+/**************************************************************************
+***************************************************************************
+
+                    main function, optimizes a mesh
+
+ **************************************************************************
+ **************************************************************************/
+
+HXTStatus hxtOptimizeTetrahedra(HXTMesh *mesh,
+                                HXTOptimizeOptions* options)
+{
+  if(options->numThreads<0)
+    options->numThreads = omp_get_num_procs();
+  else if(options->numThreads==0)
+    options->numThreads = omp_get_max_threads();
+
+  HXTBbox bbox;
+  if(options->bbox==NULL) {
+    hxtBboxAdd(&bbox, mesh->vertices.coord, mesh->vertices.num);
+  }
+  else {
+    bbox = *options->bbox;
+  }
+
+
+  ThreadShared shared;
+  HXT_CHECK( threadShared_init(mesh, options, &shared) );
+
+  ThreadLocal* locals = NULL;
+  HXT_CHECK( threadLocals_create(&locals, &shared, options) );
+
+  HXT_CHECK( hxtMoore(&bbox, (HXTVertex*) mesh->vertices.coord, mesh->vertices.num, NULL) );
+
+
+  int doSPR = 1;
+  double conflictRatio = 0.0;
+
+  uint64_t roundModifIn = UINT64_MAX;
+  uint64_t roundModifOut = UINT64_MAX;
+  // uint64_t roundBadTetOut = UINT64_MAX;
+
+  uint64_t maxBadTetIn = 0;
+  uint64_t roundBadTetIn = UINT64_MAX;
+  double lastSPRModifRatio = 0.95;
+
+  int changePartitionCurve = 0;
+  int badTetAlreadySorted = 0;
+  
+  uint32_t seed = 1;
+  volatile HXTStatus globalStatus = HXT_STATUS_OK;
+  
+  while(1) {
+    /**************************************************************************
+     * Choosing the number of threads and the method that we are going to use
+     **************************************************************************/
+    if(conflictRatio==0.0 || shared.badTets.num==0) {
+      HXT_CHECK( badTets_update(mesh, &shared) );
+
+      if(shared.badTets.num > maxBadTetIn)
+        maxBadTetIn = shared.badTets.num;
+
+      conflictFlagsInit(mesh, shared.badTets.array, shared.badTets.num);
+      if(roundModifOut==0 || shared.badTets.num==0 ||
+         (maxBadTetIn - roundBadTetIn > 1000 * roundModifOut && roundBadTetIn > 1000 * roundModifOut))
+        break;
+
+      double lastModifRatio = (double) roundModifIn/roundBadTetIn;
+      if(doSPR) {
+        lastSPRModifRatio = lastModifRatio;
+        doSPR = 0;
+        roundModifOut = 0;
+        // roundBadTetOut = shared.badTets.num;
+      }
+      else if(200.0 * lastModifRatio <= lastSPRModifRatio*lastSPRModifRatio*0.75 + lastSPRModifRatio*0.1 + 0.1) {
+        doSPR = 1;
+        roundModifOut = 0;
+        // roundBadTetOut = shared.badTets.num;
+      }
+      roundModifIn = 0;
+      roundBadTetIn = shared.badTets.num;
+      changePartitionCurve = 0;
+      badTetAlreadySorted = 0;
+      conflictRatio = 0.0;
+      shared.numThreads = options->numThreads;
+
+      HXT_INFO_COND(options->verbosity>0,
+                    "Improving %10" HXTu64 " tet. on %3d thrd %s",
+                    roundBadTetIn, shared.numThreads, doSPR ? "(SPR)":"(S & ER)");
+    }
+    else {
+      HXT_CHECK( badTets_update_among_conflicts(mesh, &shared) );
+
+      badTetAlreadySorted = 1; // because badTets_update_among_conflicts is stable
+      if((conflictRatio>0.6 || (doSPR && conflictRatio>0.2)) && shared.numThreads!=1)
+        changePartitionCurve = 1;
+      else
+        changePartitionCurve = 0;
+    }
+
+    shared.numThreads = computeNumberOfThreads(conflictRatio,
+                                                shared.numThreads,
+                                                shared.badTets.num,
+                                                doSPR ? 8 : 128);
+
+    shared.toSync.threadFinished = 0;
+
+    // create partitions
+    HXT_CHECK( threadLocals_update(mesh, &bbox, &shared, locals, &seed,
+                                   changePartitionCurve, badTetAlreadySorted) );
+
+    #pragma omp parallel num_threads(shared.numThreads)
+    {
+      int threadID = omp_get_thread_num();
+      ThreadLocal* local = &locals[threadID];
+      const uint64_t numElem = local->partition.numElem;
+      const uint64_t first = local->partition.firstElem;
+
+      for (uint64_t i=0; i<numElem && globalStatus==HXT_STATUS_OK; i++) {
+        uint64_t index = (first + i)%shared.badTets.num;
+        uint64_t curTet = shared.badTets.array[index].v[1];
+
+        if(shared.badTets.array[index].v[0] & (UINT64_C(1)<<63) || !getConflictFlag(mesh, curTet) || getDeletedFlag(mesh, curTet))
+          continue;
+
+        HXTStatus status = HXT_STATUS_OK;
+        local->stat.attempt++;
+
+        if(!doSPR) {
+          int conflict = 0;
+          for (int edge=0; edge<6; edge++) {
+            unsigned facet0, facet1;
+            getFacetsFromEdge(edge, &facet0, &facet1);
+
+            status = hxtEdgeRemoval_opti(local, curTet, edge);
+            if(status==HXT_STATUS_CONFLICT)
+              conflict = 1;
+            else if(status==HXT_STATUS_OK){
+              break;
+            }
+            else if(status>HXT_STATUS_INTERNAL) {
+              // fatal error
+              break;
+            }
+          }
+
+          /*** make a swap whenever it is possible and it is an improvement ***/
+          if(status<=HXT_STATUS_INTERNAL) {
+            for (int vertex=0; vertex<4; vertex++) {
+              status = hxtSmoothing(local, 4*curTet+vertex);
+              if(status==HXT_STATUS_CONFLICT)
+                conflict = 1;
+              else if(status==HXT_STATUS_OK) {
+                break;
+              }
+              else if(status>HXT_STATUS_INTERNAL) {
+                // fatal error
+                break;
+              }
+            }
+          }
+
+          if(status==HXT_STATUS_INTERNAL && conflict)
+            status = HXT_STATUS_CONFLICT;
+        }
+        else {
+          status = hxtSPR_opti(local, curTet);
+        }
+
+        if(status==HXT_STATUS_CONFLICT)
+          local->stat.conflict++;
+        else if(status==HXT_STATUS_OK)
+          local->stat.success++;
+        else if(status<=HXT_STATUS_INTERNAL)// the cavity could not be modified
+          unsetConflictFlag(mesh, curTet);
+        else {
+          // fatal error
+          #pragma omp atomic write
+          globalStatus = status;
+          break;
+        }
+      }
+
+      HXTStatus status = waitForPossibleReallocation(&shared.toSync, shared.numThreads);
+      if(status!=HXT_STATUS_OK) {
+        #pragma omp atomic write
+          globalStatus = status;
+      }
+    } // end of parallel section
+
+    if(globalStatus!=HXT_STATUS_OK){
+      HXT_TRACE(globalStatus);
+      return globalStatus;
+    }
+
+    if(doSPR)
+      SPRDates_update(&shared, locals);
+
+    if(options->reproducible) {
+      HXT_CHECK( reorderTetIfNeeded(mesh, locals, shared.numThreads) );
+    }
+
+    Statistic stat = threadLocals_collectStats(locals, shared.numThreads);
+    HXT_INFO_COND(options->verbosity>1,
+                  "%3d thrd |%10" HXTu64 "/%-10" HXTu64 " %" HXTu64 " conflicts",
+                  shared.numThreads, stat.success, stat.attempt, stat.conflict);
+
+    roundModifIn += stat.success;
+    roundModifOut += stat.success;
+    conflictRatio = (double) stat.conflict / stat.attempt;
+  }
+
+
+  if(options->verbosity>1) {
+    
+    uint64_t badTetNum;
+    double meanQuality;
+    double minQuality;
+    badTetrahedraStat(mesh, shared.quality.values, shared.quality.threshold,
+                      &badTetNum, &meanQuality, &minQuality);
+
+    HXT_INFO("%" HXTu64 " bad tet. | mean quality: %g | min quality: %g",
+            badTetNum, meanQuality, minQuality);
+  }
+
+
+  for (int threadID=0; threadID<options->numThreads; threadID++) {
+    for (uint64_t i=0; i<locals[threadID].deleted.num; i++) {
+      uint64_t delTet = locals[threadID].deleted.array[i];
+#ifdef DEBUG
+      if(!getDeletedFlag(mesh, delTet))
+        return HXT_ERROR_MSG(HXT_STATUS_ERROR, "deleted flag not set on deleted tet");
+#endif
+      for (int j=0; j<4; j++)
+        mesh->tetrahedra.neigh[4*delTet+j] = HXT_NO_ADJACENT;
+    }
+  }
+
+#ifdef DEBUG
+  HXT_CHECK( hxtTetVerify(mesh) );
+#endif
+
+  HXT_CHECK( hxtRemoveDeleted(mesh) );
+
+  HXT_CHECK( threadLocals_destroy(&locals, options->numThreads) );
+  HXT_CHECK( threadShared_destroy(&shared) );
+
+  return HXT_STATUS_OK;
+}
+
diff --git a/contrib/hxt/hxt_tetOpti.h b/contrib/hxt/tetMesh/src/hxt_tetOpti.h
similarity index 85%
rename from contrib/hxt/hxt_tetOpti.h
rename to contrib/hxt/tetMesh/src/hxt_tetOpti.h
index 59e61105b0..a6fab3d0ff 100644
--- a/contrib/hxt/hxt_tetOpti.h
+++ b/contrib/hxt/tetMesh/src/hxt_tetOpti.h
@@ -1,5 +1,17 @@
-#ifndef HXT_MESH_H_
-#define HXT_MESH_H_
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
+#ifndef HXT_OPTI_H
+#define HXT_OPTI_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 #include "hxt_mesh.h"
 #include "hxt_bbox.h"
@@ -26,6 +38,7 @@ typedef struct {
   uint32_t numVerticesConstrained;
 
   int verbosity;
+  int reproducible;
 
 } HXTOptimizeOptions;
 
@@ -38,4 +51,9 @@ typedef struct {
  */
 HXTStatus hxtOptimizeTetrahedra(HXTMesh *mesh,
                                 HXTOptimizeOptions* options);
+
+#ifdef __cplusplus
+}
+#endif
+
 #endif
diff --git a/contrib/hxt/tetMesh/src/hxt_tetOptiUtils.h b/contrib/hxt/tetMesh/src/hxt_tetOptiUtils.h
new file mode 100644
index 0000000000..fedf57f2e9
--- /dev/null
+++ b/contrib/hxt/tetMesh/src/hxt_tetOptiUtils.h
@@ -0,0 +1,68 @@
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
+#ifndef HXT_TETOPTIUTILS_H
+#define HXT_TETOPTIUTILS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "hxt_tetPartition.h"
+#include "hxt_tetSync.h"
+#include "hxt_tetQuality.h"
+
+typedef struct {
+  uint16_t creation;
+  uint16_t check;
+} HXTTetDate;
+
+
+typedef struct {
+  HXTTetDate* values;
+  uint16_t current;
+} HXTTetDates;
+
+
+typedef struct {
+  uint64_t attempt;
+  uint64_t conflict;
+  uint64_t success;
+} Statistic;
+
+
+typedef struct 
+{
+  /*** located here ***/
+  // list of deleted tet. Added when the cavity is created, removed when the cavity is filled
+  HXTDeleted deleted;
+  HXTPartition partition;
+  Statistic stat;
+
+  /*** located in shared structure ***/
+  HXTTetQualities* quality;
+  HXTTetDates* date;
+  HXT2Sync* toSync;
+  uint32_t numVerticesConstrained;
+
+  struct {
+    // special dates used by SPR
+    uint64_t dateOfLastCheck;
+    uint64_t dateOfLastCreation;
+
+    // maximum number of nodes in the SPR search tree
+    uint64_t maxSearchNodes;
+  } SPR;
+} ThreadLocal;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/contrib/hxt/tetMesh/src/hxt_tetPartition.h b/contrib/hxt/tetMesh/src/hxt_tetPartition.h
new file mode 100644
index 0000000000..20e5cd1509
--- /dev/null
+++ b/contrib/hxt/tetMesh/src/hxt_tetPartition.h
@@ -0,0 +1,66 @@
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
+#ifndef HXT_TETPARTITION_H
+#define HXT_TETPARTITION_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#include "hxt_vertices.h"
+
+typedef struct {
+    uint64_t startDist;
+    uint64_t lengthDist;
+    uint64_t firstElem;
+    uint64_t numElem;
+} HXTPartition;
+
+
+/* simple utility function to tell if a vertex is inside a partition,
+ * given the partition start and it's length 'rel'
+ * !!! Does not work with ghost vertex !!! */
+static inline int vertexOutOfPartition(HXTVertex* vertices, uint32_t v, uint64_t lengthDist, uint64_t startDist) {
+  // unsigned wrap around is defined by the standard
+  return vertices[v].padding.hilbertDist - startDist >= lengthDist;
+}
+
+
+static inline int computeNumberOfThreads(double conflictRatio, int numThreads, uint64_t numElem, uint64_t smallestPass)
+{
+  const double maxBorders = 8.0;
+  if(conflictRatio > (numThreads - 1) * maxBorders / ( numThreads * (maxBorders + 1) - 2.) ) {
+    numThreads = (numThreads + 1) / 2;
+  }
+
+  int maxThreadsInRound = 1;
+  {
+    uint32_t tmp = numElem/smallestPass;
+    while(tmp>1 && maxThreadsInRound < numThreads){
+      tmp = tmp/2;
+      maxThreadsInRound*=2;
+    }
+  }
+
+  if(maxThreadsInRound < numThreads)
+    return maxThreadsInRound;
+
+  return numThreads;
+}
+
+
+// HXTStatus hxtComputePartitions(HXTPartition* partitions[], int nThreads, uint64_t* hilbertDist, uint64_t n);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/contrib/hxt/tetMesh/src/hxt_tetQuality.c b/contrib/hxt/tetMesh/src/hxt_tetQuality.c
new file mode 100644
index 0000000000..31b876c3f0
--- /dev/null
+++ b/contrib/hxt/tetMesh/src/hxt_tetQuality.c
@@ -0,0 +1,70 @@
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// 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'
+double hxtTetAspectFastRatio (double a[3],  double b[3], double c[3], double d[3], void* userData) {
+  HXT_UNUSED(userData);
+  
+  double ab[3], ac[3], ad[3], bc[3], cd[3], db[3];
+  for (int i=0; i<3; i++) {
+    ab[i] = b[i] - a[i]; // AB
+    ac[i] = c[i] - a[i]; // AC
+    ad[i] = d[i] - a[i]; // AD
+  }
+ 
+  double acxad0 = ac[1]*ad[2] - ac[2]*ad[1];
+  double adxab0 = ad[1]*ab[2] - ad[2]*ab[1];
+  double abxac0 = ab[1]*ac[2] - ab[2]*ac[1];
+  double volume6 = ab[0]*acxad0 + ac[0]*adxab0 + ad[0]*abxac0;
+ 
+   // abort as early as possible
+  if(volume6<=0.0)
+    return 0.0;
+ 
+  double acxad1 = ac[2]*ad[0] - ac[0]*ad[2];
+  double acxad2 = ac[0]*ad[1] - ac[1]*ad[0];
+ 
+  double adxab1 = ad[2]*ab[0] - ad[0]*ab[2];
+  double adxab2 = ad[0]*ab[1] - ad[1]*ab[0];
+ 
+  double abxac1 = ab[2]*ac[0] - ab[0]*ac[2];
+  double abxac2 = ab[0]*ac[1] - ab[1]*ac[0];
+
+  for (int i=0; i<3; i++) {
+    db[i] = b[i] - d[i]; // DB = B-D = AB-AD
+    bc[i] = c[i] - b[i]; // BC = C-B = AC-AB
+    cd[i] = d[i] - c[i]; // CD = D-c = AD-AC
+  }
+ 
+  double bcxcd0 = bc[1]*cd[2] - bc[2]*cd[1]; // = acxad0+abxac0+adxab0;
+  double bcxcd1 = bc[2]*cd[0] - bc[0]*cd[2]; // = acxad1+abxac1+adxab1;
+  double bcxcd2 = bc[0]*cd[1] - bc[1]*cd[0]; // = acxad2+abxac2+adxab2;
+
+  double areaSum = sqrt(acxad0*acxad0 + acxad1*acxad1 + acxad2*acxad2)
+                 + sqrt(adxab0*adxab0 + adxab1*adxab1 + adxab2*adxab2)
+                 + sqrt(abxac0*abxac0 + abxac1*abxac1 + abxac2*abxac2)
+                 + sqrt(bcxcd0*bcxcd0 + bcxcd1*bcxcd1 + bcxcd2*bcxcd2);
+
+  double l = ab[0]*ab[0] + ab[1]*ab[1] + ab[2]*ab[2]; // |AB|²
+  double l2 = ac[0]*ac[0] + ac[1]*ac[1] + ac[2]*ac[2]; // |AC|²
+  double l3 = ad[0]*ad[0] + ad[1]*ad[1] + ad[2]*ad[2]; // |AD|²
+  double l4 = bc[0]*bc[0] + bc[1]*bc[1] + bc[2]*bc[2]; // |BC|²
+  double l5 = cd[0]*cd[0] + cd[1]*cd[1] + cd[2]*cd[2]; // |CD|²
+  double l6 = db[0]*db[0] + db[1]*db[1] + db[2]*db[2]; // |DB|²
+
+  if(l2>l) l=l2;
+  if(l3>l) l=l3;
+  if(l4>l) l=l4;
+  if(l5>l) l=l5;
+  if(l6>l) l=l6;
+
+  return volume6*volume6/(l*areaSum*areaSum);
+}
\ No newline at end of file
diff --git a/contrib/hxt/hxt_tetQuality.h b/contrib/hxt/tetMesh/src/hxt_tetQuality.h
similarity index 73%
rename from contrib/hxt/hxt_tetQuality.h
rename to contrib/hxt/tetMesh/src/hxt_tetQuality.h
index 77de220484..f93db5b25a 100644
--- a/contrib/hxt/hxt_tetQuality.h
+++ b/contrib/hxt/tetMesh/src/hxt_tetQuality.h
@@ -1,12 +1,20 @@
-#ifndef _HXT_TETQUALITY_
-#define _HXT_TETQUALITY_
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
+#ifndef HXT_TETQUALITY_H
+#define HXT_TETQUALITY_H
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 #include "hxt_mesh.h"
-#include <float.h>
+#include <math.h>
 
 typedef struct {
   double* values;   // qualities for all tet.
@@ -15,21 +23,15 @@ typedef struct {
   void* userData;
 } HXTTetQualities;
 
-double hxtTetDeterminantInexact(double p0[3],  double p1[3], double p2[3], double p3[3], void* userData);
-
-/// TODO: make an optimized version of this
-double hxtTetAspectRatio(double p0[3],  double p1[3], double p2[3], double p3[3], void* userData);
-
 //!\ this function does not return the aspect ratio 'r'. It returns 'r^2/24'
 double hxtTetAspectFastRatio(double p0[3],  double p1[3], double p2[3], double p3[3], void* userData);
 // double myOwnAspectRatio(double a[3],  double b[3], double c[3], double d[3]);
 
+static inline double hxtTetAspectRatio(double p0[3],  double p1[3], double p2[3], double p3[3], void* userData){
+  return sqrt(24.*hxtTetAspectFastRatio(p0, p1, p2, p3, userData));
+}
 
 
-
-/*
- Compute the squared aspect ratio of a tet with vertices p0 p1 p2 p3
-*/
 static inline double tetQuality(HXTMesh *mesh,
                                 HXTTetQualities* quality,
                                 uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3)
diff --git a/contrib/hxt/hxt_tetRefine.c b/contrib/hxt/tetMesh/src/hxt_tetRefine.c
similarity index 55%
rename from contrib/hxt/hxt_tetRefine.c
rename to contrib/hxt/tetMesh/src/hxt_tetRefine.c
index 6bca8f4e28..04443028ea 100644
--- a/contrib/hxt/hxt_tetRefine.c
+++ b/contrib/hxt/tetMesh/src/hxt_tetRefine.c
@@ -1,6 +1,16 @@
-#include "hxt_tetRefine.h"
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
+#include <math.h>
+#include "hxt_tetDelaunay.h"
 #include "predicates.h"
 #include "hxt_tetFlag.h"
+#include "hxt_omp.h"
 
 
 HXTStatus hxtEmptyMesh(HXTMesh* mesh, HXTDelaunayOptions* delOptions)
@@ -11,23 +21,6 @@ HXTStatus hxtEmptyMesh(HXTMesh* mesh, HXTDelaunayOptions* delOptions)
   if (mesh->triangles.num == 0)  
     return HXT_ERROR_MSG(HXT_STATUS_FAILED, "The input mesh should contain triangles");
 
-  double minDist2 = DBL_MAX;
-  #pragma omp parallel for reduction(min:minDist2)
-  for (uint64_t i=0; i<mesh->triangles.num; i++){
-    uint32_t* node = mesh->triangles.node + 3*i;
-    for (int j=0; j<3; j++) {
-      double* n1 = mesh->vertices.coord + (size_t) 4*node[j];
-      double* n2 = mesh->vertices.coord + (size_t) 4*node[(j+1)%3];
-
-      double dist2 = (n1[0]-n2[0])*(n1[0]-n2[0])
-                   + (n1[1]-n2[1])*(n1[1]-n2[1])
-                   + (n1[2]-n2[2])*(n1[2]-n2[2]);
-
-      if(dist2<minDist2)
-        minDist2 = dist2;
-    }
-  }
-
   hxtNodeInfo* nodeInfo;
   HXT_CHECK( hxtAlignedMalloc(&nodeInfo, sizeof(hxtNodeInfo)*mesh->vertices.num) );
 
@@ -44,7 +37,7 @@ HXTStatus hxtEmptyMesh(HXTMesh* mesh, HXTDelaunayOptions* delOptions)
   #pragma omp parallel for simd aligned(nodeInfo:SIMD_ALIGN)
   for (uint32_t i=0; i<mesh->vertices.num; i++) {
     if(nodeInfo[i].status!=HXT_STATUS_TRUE){
-      HXT_WARNING("vertex %u of the empty mesh was not inserted\n", nodeInfo[i].node);
+      HXT_WARNING("point %u of the empty mesh was not inserted\n", nodeInfo[i].node);
     }
   }
 #endif
@@ -55,10 +48,6 @@ HXTStatus hxtEmptyMesh(HXTMesh* mesh, HXTDelaunayOptions* delOptions)
 }
 
 
-
-// refine 
-
-
 double hxtTetCircumcenter(double a[3], double b[3], double c[3], double d[3],
                             double circumcenter[3], double *xi, double *eta, double *zeta)
 {
@@ -146,11 +135,10 @@ static inline double square_dist(double v0[3], double v1[3])
 }
 
 
-static int is_too_close(HXTMesh* mesh, double tetNodeSize, double vtaSize,
-                        double squareDist)
+static int is_too_close(double ptSize, double vtaSize, double squareDist)
 {
-  if(tetNodeSize!=DBL_MAX) {
-    double meanSize = 0.5*(tetNodeSize+vtaSize);
+  if(ptSize!=DBL_MAX) {
+    double meanSize = 0.5*(ptSize+vtaSize);
     if(squareDist < /*(0.94*0.94) * */meanSize * meanSize) {
       return 1;
     }
@@ -160,6 +148,115 @@ static int is_too_close(HXTMesh* mesh, double tetNodeSize, double vtaSize,
 }
 
 
+/* receives the 4 nodalSize of the node of a tet, as well as the barycentric
+ * coordinates of a point in the tet, and returns the nodalSize at that point */
+static inline double getNodalSizeFromBary(double* nodalSize, double* bary)
+{
+  double denom = 0.0;
+  double num = 0.0;
+  int ndef = 0;
+  for (int j=0;j<4;j++){
+    double size = nodalSize[j];
+    if (size != DBL_MAX){
+      double weight = bary[j];
+      denom += weight;
+      num += weight * size;
+    }
+    else {
+      ndef++;
+    }
+  }
+
+  if(ndef!=4) {
+    return num/denom;
+  }
+  else {
+    HXT_WARNING("tetrahedron with undefined size");
+    return DBL_MAX;
+  }
+}
+
+
+/* receives the 4 nodalSize of the node of a tet, and returns barycentric
+ * coordinates that are proportional to the inverse of the nodalSize. */
+static inline double getBaryFromNodalSize(double* nodalSize, double* bary) {
+  double denom = 0.0;
+  int ndef = 0;
+  for (int j=0; j<4; j++)
+  {
+    double size = nodalSize[j];
+    if(size!=DBL_MAX && size!=0.0) {
+      bary[j] = 1./size;
+      denom += bary[j];
+    }
+    else {
+      bary[j] = -1.0;
+      ndef++;
+    }
+  }
+
+  if(ndef && ndef!=4) {
+    denom *= 4.0/(4.0-ndef);
+  }
+
+  for (int j=0; j<4; j++)
+  {
+    if(bary[j]==-1.0) {
+      bary[j] = 0.25;
+    }
+    else {
+      bary[j] /= denom;
+    }
+  }
+
+  if(ndef!=4) {
+    return 4.0/denom;
+  }
+  else {
+    HXT_WARNING("tetrahedron with undefined size");
+    return DBL_MAX;
+  }
+}
+
+
+/* just fill tetCoord and tetNodalSize with the coordinates and nodal size of each node of
+ * tetrahedron tet */
+static inline void getTetCoordAndNodalSize(HXTMesh* mesh, double* nodalSizes, uint64_t tet,
+                                           double tetCoord[4][4], double tetNodalSize[4])
+{
+  uint32_t* nodes = &mesh->tetrahedra.node[4*tet];
+  for(int i=0; i<4; i++) {
+    tetCoord[i][0] = mesh->vertices.coord[4 * nodes[i] + 0];
+    tetCoord[i][1] = mesh->vertices.coord[4 * nodes[i] + 1];
+    tetCoord[i][2] = mesh->vertices.coord[4 * nodes[i] + 2];
+
+    tetNodalSize[i] = nodalSizes[nodes[i]];
+  }
+}
+
+
+
+// HXTStatus hxtRefineTetrahedraFirst(HXTMesh* mesh, HXTDelaunayOptions* delOptions,
+//                                    double (*meshSizeFun)(double x, double y, double z,
+//                                                          void* meshSizeData),
+//                                    void* meshSizeData)
+// {
+
+//   #pragma omp parallel for
+//   for(uint64_t i=0; i<mesh->tetrahedra.num; i++) {
+    
+//     if(getProcessedFlag(mesh, i))
+//       continue;
+
+//     // we got to turn around each edge :p
+//   }
+
+//   HXT_CHECK(hxtDelaunay(mesh, delOptions));
+
+//   return HXT_STATUS_OK;
+// }
+
+
 HXTStatus hxtRefineTetrahedra(HXTMesh* mesh, HXTDelaunayOptions* delOptions,
                               double (*meshSizeFun)(double x, double y, double z,
                                                     void* meshSizeData),
@@ -180,23 +277,15 @@ HXTStatus hxtRefineTetrahedra(HXTMesh* mesh, HXTDelaunayOptions* delOptions,
     uint64_t numToProcessPerThread;
     {
       // get the number of unprocessed tet to avid wasting memory ressources...
-      uint64_t hxtDeclareAligned64 numToProcessSIMD[4] = {0};
-      for(uint64_t i=0; i<mesh->tetrahedra.num/4; i++) {
-        numToProcessSIMD[0] += getProcessedFlag(mesh, i*4+0)==0;
-        numToProcessSIMD[1] += getProcessedFlag(mesh, i*4+1)==0;
-        numToProcessSIMD[2] += getProcessedFlag(mesh, i*4+2)==0;
-        numToProcessSIMD[3] += getProcessedFlag(mesh, i*4+3)==0;
-      }
-
-      for(uint64_t i=mesh->tetrahedra.num/4*4; i<mesh->tetrahedra.num; i++) {
-        numToProcessSIMD[0] += getProcessedFlag(mesh, i)==0;
+      uint64_t numToProcess = 0;
+      for(uint64_t i=0; i<mesh->tetrahedra.num; i++) {
+        numToProcess += getProcessedFlag(mesh, i)==0;
       }
 
       // each thread will have to process a certain number of tet
-      numToProcessPerThread =((numToProcessSIMD[0]+numToProcessSIMD[1]) +
-                              (numToProcessSIMD[2]+numToProcessSIMD[3]))/maxThreads + 1;
+      numToProcessPerThread = numToProcess/maxThreads + 1;
 
-      uint64_t numToProcess = 0;
+      numToProcess = 0;
       uint64_t step = 0;
       int threadID = 0;
       for(uint64_t i=0; i<mesh->tetrahedra.num; i++) {
@@ -216,10 +305,9 @@ HXTStatus hxtRefineTetrahedra(HXTMesh* mesh, HXTDelaunayOptions* delOptions,
 
 
 
-    
     uint32_t add = 0;
     HXTStatus status = HXT_STATUS_OK;
-    #pragma omp parallel reduction(+:add)
+    #pragma omp parallel
     {
       int threadID = omp_get_thread_num();
 
@@ -228,141 +316,86 @@ HXTStatus hxtRefineTetrahedra(HXTMesh* mesh, HXTDelaunayOptions* delOptions,
 
       for(uint64_t i=startIndex[threadID]; i<startIndex[threadID+1]; i++) {
 
-        if (getProcessedFlag(mesh, i)==0){
-          int pointAdded = 0;
-          double* p[4];
-          p[0] = mesh->vertices.coord + (size_t) 4*mesh->tetrahedra.node[4*i+0];
-          p[1] = mesh->vertices.coord + (size_t) 4*mesh->tetrahedra.node[4*i+1];
-          p[2] = mesh->vertices.coord + (size_t) 4*mesh->tetrahedra.node[4*i+2];
-          p[3] = mesh->vertices.coord + (size_t) 4*mesh->tetrahedra.node[4*i+3];
-          double newCoord [3];
-          double bary[4];
-          double vtaSize;
-          setProcessedFlag(mesh, i); // we do not need to refine that tetrahedra anymore
-
-          double tetNodeSize[4];
-          for(int j=0; j<4; j++) {
-            tetNodeSize[j] = delOptions->nodalSizes[mesh->tetrahedra.node[4*i+j]];
-          }
+        if (getProcessedFlag(mesh, i))
+          continue;
+
+        setProcessedFlag(mesh, i); // we do not need to refine that tetrahedron anymore
+
+        int pointAdded = 0;
+        double p[4][4];
+        double s[4];
+        double bary[4];
+        double newCoord [3];
+        double vtaSize;
+        getTetCoordAndNodalSize(mesh, delOptions->nodalSizes, i, p, s);
 
-          // try to add the point at the circumcenter
-          hxtTetCircumcenter(p[0], p[1], p[2], p[3], newCoord, &bary[1], &bary[2], &bary[3]);
-          bary[0] = 1.0 - bary[1] - bary[2] - bary[3];
-
-          // we don't insert at circumcenter if it is outside the tet.
-          if(bary[0] > 0 && bary[1] > 0 && bary[2] > 0 && bary[3] > 0) {
-
-            // computing the mesh size
-            if(meshSizeFun!=NULL) {
-              vtaSize = meshSizeFun(newCoord[0], newCoord[1], newCoord[2], meshSizeData);
-            }
-            else { // we suppose delOptions->nodalSize!=NULL
-              double denom = 0.0;
-              double num = 0.0;
-              for (int j=0;j<4;j++){
-                double size = delOptions->nodalSizes[mesh->tetrahedra.node[4*i+j]];
-                if (size != DBL_MAX){
-                  if(bary[j]>0.999) {
-                    num = size;
-                    denom = 1;
-                    break;
-                  }
-                  double weight = bary[j];
-                  denom += weight;
-                  num += weight * size;
-                }
-              }
-
-              vtaSize = num/denom;
-            }
-
-            double circumradius2 = square_dist(p[0], newCoord);
-            
-            if(!is_too_close(mesh, tetNodeSize[0], vtaSize, circumradius2) &&
-               !is_too_close(mesh, tetNodeSize[1], vtaSize, circumradius2) &&
-               !is_too_close(mesh, tetNodeSize[2], vtaSize, circumradius2) &&
-               !is_too_close(mesh, tetNodeSize[3], vtaSize, circumradius2)) {
-              size_t vertexIndex = vertexStart + localAdd;
-              newVertices[vertexIndex*4  ] = newCoord[0];
-              newVertices[vertexIndex*4+1] = newCoord[1];
-              newVertices[vertexIndex*4+2] = newCoord[2];
-              newVertices[vertexIndex*4+3] = vtaSize;
-              pointAdded = 1;
-              localAdd++;
-            }
+        // try to add the point at the circumcenter
+        hxtTetCircumcenter(p[0], p[1], p[2], p[3], newCoord, &bary[1], &bary[2], &bary[3]);
+        bary[0] = 1.0 - bary[1] - bary[2] - bary[3];
+
+        // we don't insert at circumcenter if it is outside the tet.
+        if(bary[0] > 0 && bary[1] > 0 && bary[2] > 0 && bary[3] > 0) {
+
+          // computing the mesh size
+          if(meshSizeFun!=NULL) {
+            vtaSize = meshSizeFun(newCoord[0], newCoord[1], newCoord[2], meshSizeData);
+          }
+          else { // we suppose delOptions->nodalSize!=NULL
+            vtaSize = getNodalSizeFromBary(s, bary);
           }
+
+          double circumradius2 = square_dist(p[0], newCoord);
           
-          // try to add the point at barycentric coordinates
-          // ponderated by the inverse of the mesh size
-          if(!pointAdded){
-            double denom = 0.0;
-            int ndef = 0;
-            for (int j=0; j<4; j++)
-            {
-              double size = tetNodeSize[j];
-              if(size!=DBL_MAX && size!=0.0) {
-                bary[j] = 1./size;
-                denom += bary[j];
-              }
-              else {
-                bary[j] = -1.0;
-                ndef++;
-              }
-            }
-
-            if(ndef && ndef!=4) {
-              denom *= 4.0/(4.0-ndef);
-            }
-
-            for (int j=0; j<4; j++)
-            {
-              if(bary[j]==-1.0) {
-                bary[j] = 0.25;
-              }
-              else {
-                bary[j] /= denom;
-              }
-            }
-
-            for (int j=0; j<3; j++)
-            {
-              newCoord[j] = bary[0]*p[0][j] +
-                            bary[1]*p[1][j] +
-                            bary[2]*p[2][j] +
-                            bary[3]*p[3][j];
-            }
-
-            // this does not work with ffast-math, GCC completely ignore this...
-  #if !defined(__FAST_MATH__) && !defined(NDEBUG)
-            if(!isfinite(newCoord[0]) || !isfinite(newCoord[1]) || !isfinite(newCoord[2])){
-              HXT_ERROR_MSG(HXT_STATUS_ERROR, "new coordinates are not finite");
-              exit(EXIT_FAILURE);
-            }
-  #endif
-
-            if(meshSizeFun!=NULL) {
-              vtaSize = meshSizeFun(newCoord[0], newCoord[1], newCoord[2], meshSizeData);
-            }
-            else {
-              if(ndef==4)
-                vtaSize = DBL_MAX;
-              else {
-                vtaSize = 4.0/denom;
-              }
-            }
-
-            if(!is_too_close(mesh, tetNodeSize[0], vtaSize, square_dist(p[0], newCoord)) &&
-               !is_too_close(mesh, tetNodeSize[1], vtaSize, square_dist(p[1], newCoord)) &&
-               !is_too_close(mesh, tetNodeSize[2], vtaSize, square_dist(p[2], newCoord)) &&
-               !is_too_close(mesh, tetNodeSize[3], vtaSize, square_dist(p[3], newCoord))){
-              size_t vertexIndex = vertexStart + localAdd;
-              newVertices[vertexIndex*4  ] = newCoord[0];
-              newVertices[vertexIndex*4+1] = newCoord[1];
-              newVertices[vertexIndex*4+2] = newCoord[2];
-              newVertices[vertexIndex*4+3] = vtaSize;
-              pointAdded = 1;
-              localAdd++;
-            }
+          if(!is_too_close(s[0], vtaSize, circumradius2) &&
+             !is_too_close(s[1], vtaSize, circumradius2) &&
+             !is_too_close(s[2], vtaSize, circumradius2) &&
+             !is_too_close(s[3], vtaSize, circumradius2)) {
+            size_t vertexIndex = vertexStart + localAdd;
+            newVertices[vertexIndex*4  ] = newCoord[0];
+            newVertices[vertexIndex*4+1] = newCoord[1];
+            newVertices[vertexIndex*4+2] = newCoord[2];
+            newVertices[vertexIndex*4+3] = vtaSize;
+            pointAdded = 1;
+            localAdd++;
+          }
+        }
+        
+        // try to add the point at barycentric coordinates
+        // ponderated by the inverse of the mesh size
+        if(!pointAdded){
+          vtaSize = getBaryFromNodalSize(s, bary);
+
+          for (int j=0; j<3; j++)
+          {
+            newCoord[j] = bary[0]*p[0][j] +
+                          bary[1]*p[1][j] +
+                          bary[2]*p[2][j] +
+                          bary[3]*p[3][j];
+          }
+
+          // this does not work with ffast-math, GCC completely ignore this...
+#if !defined(__FAST_MATH__) && !defined(NDEBUG)
+          if(!isfinite(newCoord[0]) || !isfinite(newCoord[1]) || !isfinite(newCoord[2])){
+            HXT_ERROR_MSG(HXT_STATUS_ERROR, "new coordinates are not finite");
+            exit(EXIT_FAILURE);
+          }
+#endif
+
+          if(meshSizeFun!=NULL) {
+            vtaSize = meshSizeFun(newCoord[0], newCoord[1], newCoord[2], meshSizeData);
+          }
+
+          if(!is_too_close(s[0], vtaSize, square_dist(p[0], newCoord)) &&
+             !is_too_close(s[1], vtaSize, square_dist(p[1], newCoord)) &&
+             !is_too_close(s[2], vtaSize, square_dist(p[2], newCoord)) &&
+             !is_too_close(s[3], vtaSize, square_dist(p[3], newCoord))){
+            size_t vertexIndex = vertexStart + localAdd;
+            newVertices[vertexIndex*4  ] = newCoord[0];
+            newVertices[vertexIndex*4+1] = newCoord[1];
+            newVertices[vertexIndex*4+2] = newCoord[2];
+            newVertices[vertexIndex*4+3] = vtaSize;
+            pointAdded = 1;
+            localAdd++;
           }
         }
       }
@@ -381,6 +414,8 @@ HXTStatus hxtRefineTetrahedra(HXTMesh* mesh, HXTDelaunayOptions* delOptions,
           add = tsum;
         }
 
+        HXT_INFO_COND(delOptions->verbosity>1, "Refinement adds %u points", add);
+
         if(mesh->vertices.num + add>mesh->vertices.size){
           status=hxtAlignedRealloc(&mesh->vertices.coord, sizeof(double)*4*(mesh->vertices.num + add));
           if(status==HXT_STATUS_OK){
@@ -409,9 +444,14 @@ HXTStatus hxtRefineTetrahedra(HXTMesh* mesh, HXTDelaunayOptions* delOptions,
       return status;
     }
 
+    HXT_CHECK(hxtAlignedFree(&newVertices));
+
+    if(add == 0)
+      break;
+
     mesh->vertices.num += add;
 
-    HXT_CHECK(hxtAlignedFree(&newVertices));
+    delOptions->partitionability = 1.0 - pow(0.5, iter);
     
     HXT_CHECK(hxtDelaunay(mesh, delOptions));
 
diff --git a/contrib/hxt/hxt_tetRefine.h b/contrib/hxt/tetMesh/src/hxt_tetRefine.h
similarity index 73%
rename from contrib/hxt/hxt_tetRefine.h
rename to contrib/hxt/tetMesh/src/hxt_tetRefine.h
index 368d5c3c7b..c0e208e553 100644
--- a/contrib/hxt/hxt_tetRefine.h
+++ b/contrib/hxt/tetMesh/src/hxt_tetRefine.h
@@ -1,10 +1,15 @@
-#ifndef _HXT_TETREFINE_
-#define _HXT_TETREFINE_
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
 
-#include "hxt_tetDelaunay.h"
+#ifndef HXT_TETREFINE_H
+#define HXT_TETREFINE_H
 
-/// Creates a structure that allows to look over triangular faces of the 2D mesh
-HXTStatus hxtCreateFaceSearchStructure(HXTMesh* mesh, uint32_t **pfaces);
+#include "hxt_tetDelaunay.h"
 
 //// creates a mesh with all points of the surface mesh
 HXTStatus hxtEmptyMesh(HXTMesh* mesh, HXTDelaunayOptions* delOptions);
diff --git a/contrib/hxt/hxt_tetRepair.c b/contrib/hxt/tetMesh/src/hxt_tetRepair.c
similarity index 75%
rename from contrib/hxt/hxt_tetRepair.c
rename to contrib/hxt/tetMesh/src/hxt_tetRepair.c
index 2df4c551fa..43096a5f46 100644
--- a/contrib/hxt/hxt_tetRepair.c
+++ b/contrib/hxt/tetMesh/src/hxt_tetRepair.c
@@ -1,3 +1,11 @@
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
 #include "hxt_tetRepair.h"
 #include "hxt_tetUtils.h"
 #include "hxt_tetFlag.h"
@@ -285,6 +293,13 @@ HXTStatus hxtTetVerify(HXTMesh* mesh)
   volatile int errorOccured = 0;
   HXTVertex* vertices = (HXTVertex*) mesh->vertices.coord;
 
+  if(mesh->tetrahedra.node==NULL && mesh->tetrahedra.num!=0) {
+    return HXT_ERROR_MSG(HXT_STATUS_ERROR, "list of nodes not given");
+  }
+
+  if(mesh->tetrahedra.neigh==NULL && mesh->tetrahedra.num!=0)
+    HXT_WARNING("adjacencies not computed");
+
   #pragma omp parallel for
   for (uint64_t i=0; i<mesh->tetrahedra.num; i++)
   {
@@ -293,17 +308,29 @@ HXTStatus hxtTetVerify(HXTMesh* mesh)
     //   continue;
 
     uint32_t* Node = mesh->tetrahedra.node + i*4;
-    uint64_t* Neigh = mesh->tetrahedra.neigh + i*4;
 
-    if(getDeletedFlag(mesh, i)){
+    if(mesh->tetrahedra.flag && getDeletedFlag(mesh, i)){
       // HXT_WARNING("deleted tetrahedra remain in the mesh");
       continue;
     }
 
     // check for good placement of ghost vertex
-    if(Node[0]==HXT_GHOST_VERTEX || Node[1]==HXT_GHOST_VERTEX || Node[2]==HXT_GHOST_VERTEX){
-      HXT_ERROR_MSG(HXT_STATUS_ERROR, "ghost vertex at wrong place in tet. %lu", i);
-      errorOccured=1;
+    int localError = 0;
+    for(int j=0; j<4; j++) {
+      if(Node[j]==HXT_GHOST_VERTEX){
+        if(j!=3) {
+          HXT_ERROR_MSG(HXT_STATUS_ERROR, "ghost vertex at wrong place in tet. %lu", i);
+          localError=1;
+        }
+      }
+      else if(Node[j]>=mesh->vertices.num){
+        HXT_ERROR_MSG(HXT_STATUS_ERROR, "node %d of tet. %lu does not exist", j, i);
+        localError=2;
+      }
+    }
+
+    if(localError) {
+      errorOccured = localError;
       continue;
     }
 
@@ -318,85 +345,88 @@ HXTStatus hxtTetVerify(HXTMesh* mesh)
     // else
     if(Node[3]!=HXT_GHOST_VERTEX && orient3d(a,b,c,vertices[Node[3]].coord)>=0.0){
       HXT_ERROR_MSG(HXT_STATUS_ERROR, "orientation of tet %lu is wrong",i);
-      errorOccured=1;
+      errorOccured=3;
       continue;
     }
 
-    // check the neighbors
-    for (unsigned j=0; j<4; j++)
-    {
-      if(Neigh[j]==HXT_NO_ADJACENT){
-        continue;
-      }
+    if(mesh->tetrahedra.neigh) {
+      uint64_t* Neigh = mesh->tetrahedra.neigh + i*4;
 
-      uint64_t neigh = Neigh[j]/4;
-      unsigned face = Neigh[j]%4;
+      // check the neighbors
+      for (unsigned j=0; j<4; j++)
+      {
+        if(Neigh[j]==HXT_NO_ADJACENT){
+          continue;
+        }
 
-      if(neigh>=mesh->tetrahedra.num) {
-        HXT_ERROR_MSG(HXT_STATUS_ERROR, "%uth neighbor of tet %lu does not exist", j, i);
-        errorOccured=1;
-        continue;
-      }
+        uint64_t neigh = Neigh[j]/4;
+        unsigned face = Neigh[j]%4;
 
-      if(getDeletedFlag(mesh, neigh)) {
-        HXT_ERROR_MSG(HXT_STATUS_ERROR, "%uth neighbor of tet %lu is deleted", j, i);
-        errorOccured=1;
-        continue;
-      }
+        if(neigh>=mesh->tetrahedra.num) {
+          HXT_ERROR_MSG(HXT_STATUS_ERROR, "%uth neighbor of tet %lu does not exist", j, i);
+          errorOccured=4;
+          continue;
+        }
 
-      // uint64_t* NeighNeigh = mesh->tetrahedra.neigh + neigh;
-      uint32_t* NeighNode = mesh->tetrahedra.node + neigh*4;
-      
-      if(mesh->tetrahedra.neigh[4*neigh+face]!=i*4+j){
-        HXT_ERROR_MSG(HXT_STATUS_ERROR, "tet %lu (%lu/4) is not the neighbor of its %uth neighbor %lu (%lu/4)", i, i*4,j, neigh, 4*neigh+face);
-        errorOccured=1;
-        continue;
-      }
+        if(mesh->tetrahedra.flag && getDeletedFlag(mesh, neigh)) {
+          HXT_ERROR_MSG(HXT_STATUS_ERROR, "%uth neighbor of tet %lu is deleted", j, i);
+          errorOccured=5;
+          continue;
+        }
 
-      uint32_t V[3] = { Node[((j+1)&3)], Node[((j+3)&2)], Node[((j&2)^3)]};
-      unsigned l;
+        // uint64_t* NeighNeigh = mesh->tetrahedra.neigh + neigh;
+        uint32_t* NeighNode = mesh->tetrahedra.node + neigh*4;
+        
+        if(mesh->tetrahedra.neigh[4*neigh+face]!=i*4+j){
+          HXT_ERROR_MSG(HXT_STATUS_ERROR, "tet %lu (%lu/4) is not the neighbor of its %uth neighbor %lu (%lu/4)", i, i*4,j, neigh, 4*neigh+face);
+          errorOccured=6;
+          continue;
+        }
 
-      for (l=0; l<3; l++)
-      {
-        if(NeighNode[((face+1)&3)]==V[l] && NeighNode[((face+3)&2)]==V[(l+1)%3] && NeighNode[((face&2)^3)]==V[(l+2)%3])
-           break;
-      }
+        uint32_t V[3] = { Node[getNode0FromFacet(j)], Node[getNode1FromFacet(j)], Node[getNode2FromFacet(j)]};
+        unsigned l;
 
-      if(l!=3){
-        HXT_ERROR_MSG(HXT_STATUS_ERROR, "neighbor %u of tet. %lu is intersecting it (common face has the same orientation)",j,i);
-        errorOccured=1;
-        continue;
-      }
+        for (l=0; l<3; l++)
+        {
+          if(NeighNode[getNode0FromFacet(face)]==V[l] && NeighNode[getNode1FromFacet(face)]==V[(l+1)%3] && NeighNode[getNode2FromFacet(face)]==V[(l+2)%3])
+             break;
+        }
 
-      for (l=0; l<3; l++)
-      {
-        if(NeighNode[((face+1)&3)]==V[l] && NeighNode[((face&2)^3)]==V[(l+1)%3] && NeighNode[((face+3)&2)]==V[(l+2)%3])
-           break;
-      }
+        if(l!=3){
+          HXT_ERROR_MSG(HXT_STATUS_ERROR, "neighbor %u of tet. %lu is intersecting it (common face has the same orientation)",j,i);
+          errorOccured=7;
+          continue;
+        }
 
-      if(l==3){
-        HXT_ERROR_MSG(HXT_STATUS_ERROR, "neighbor %u of tet. %lu doesn't contain 3 common vertices",j,i);
-        errorOccured=1;
-        continue;
-      }
+        for (l=0; l<3; l++)
+        {
+          if(NeighNode[getNode0FromFacet(face)]==V[l] && NeighNode[getNode2FromFacet(face)]==V[(l+1)%3] && NeighNode[getNode1FromFacet(face)]==V[(l+2)%3])
+             break;
+        }
+
+        if(l==3){
+          HXT_ERROR_MSG(HXT_STATUS_ERROR, "neighbor %u of tet. %lu doesn't contain 3 common vertices",j,i);
+          errorOccured=8;
+          continue;
+        }
 
+        if(mesh->tetrahedra.flag && (getFacetConstraint(mesh, i,j)!=0) ^ (getFacetConstraint(mesh, neigh, face)!=0)) {
+          HXT_ERROR_MSG(HXT_STATUS_ERROR, "constraint is not consistent on both side of facet 4*%lu+%u",i,j);
+          errorOccured=9;
+          continue;
+        }
 
-      if((getFacetConstraint(mesh, i,j)!=0) ^ (getFacetConstraint(mesh, neigh, face)!=0)) {
-        HXT_ERROR_MSG(HXT_STATUS_ERROR, "constraint is not consistent on both side of facet 4*%lu+%u",i,j);
-        errorOccured=1;
-        continue;
+        // only for delaunay triangulation...
+        // if(Node[3]!=HXT_GHOST_VERTEX && NeighNode[face]!=HXT_GHOST_VERTEX && insphere(vertices[Node[0]].coord,
+        //             vertices[Node[1]].coord,
+        //             vertices[Node[2]].coord,
+        //             vertices[Node[3]].coord,
+        //             vertices[NeighNode[face]].coord)<0.0){
+        //   HXT_ERROR_MSG(HXT_STATUS_ERROR, "neighbor %u of tet %lu has it's non-common node in the sphere (insphere(%u %u %u %u %u)>0)",j,i*4, Node[0], Node[1], Node[2], Node[3], NeighNode[face]);
+        //   errorOccured=1;
+        //   continue;
+        // }
       }
-
-      // only for delaunay triangulation...
-      // if(Node[3]!=HXT_GHOST_VERTEX && NeighNode[face]!=HXT_GHOST_VERTEX && insphere(vertices[Node[0]].coord,
-      //             vertices[Node[1]].coord,
-      //             vertices[Node[2]].coord,
-      //             vertices[Node[3]].coord,
-      //             vertices[NeighNode[face]].coord)<0.0){
-      //   HXT_ERROR_MSG(HXT_STATUS_ERROR, "neighbor %u of tet %lu has it's non-common node in the sphere (insphere(%u %u %u %u %u)>0)",j,i*4, Node[0], Node[1], Node[2], Node[3], NeighNode[face]);
-      //   errorOccured=1;
-      //   continue;
-      // }
     }
   }
 
@@ -492,11 +522,13 @@ HXTStatus hxtAddGhosts(HXTMesh* mesh){
             if(getFacetConstraint(mesh, i, j))
               setFacetConstraint(mesh, newGhost, 3);
 
+            setProcessedFlag(mesh, newGhost);
+
             uint32_t v0, v1, v2;
 
-            v0 = mesh->tetrahedra.node[4*i+((j+1)&3)];
-            v1 = mesh->tetrahedra.node[4*i+((j+3)&2)];
-            v2 = mesh->tetrahedra.node[4*i+((j&2)^3)];
+            v0 = mesh->tetrahedra.node[4*i+getNode0FromFacet(j)];
+            v1 = mesh->tetrahedra.node[4*i+getNode2FromFacet(j)];
+            v2 = mesh->tetrahedra.node[4*i+getNode1FromFacet(j)];
 
             mesh->tetrahedra.node[4*newGhost+0] = v0;
             mesh->tetrahedra.node[4*newGhost+1] = v1;
diff --git a/contrib/hxt/hxt_tetRepair.h b/contrib/hxt/tetMesh/src/hxt_tetRepair.h
similarity index 83%
rename from contrib/hxt/hxt_tetRepair.h
rename to contrib/hxt/tetMesh/src/hxt_tetRepair.h
index 0ae279a995..f7acd56708 100644
--- a/contrib/hxt/hxt_tetRepair.h
+++ b/contrib/hxt/tetMesh/src/hxt_tetRepair.h
@@ -1,5 +1,13 @@
-#ifndef _HXT_TETREPAIR_
-#define _HXT_TETREPAIR_
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
+#ifndef HXT_TETREPAIR_H
+#define HXT_TETREPAIR_H
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/contrib/hxt/hxt_tetSync.c b/contrib/hxt/tetMesh/src/hxt_tetSync.c
similarity index 92%
rename from contrib/hxt/hxt_tetSync.c
rename to contrib/hxt/tetMesh/src/hxt_tetSync.c
index 3ed97de3b0..2458194f71 100644
--- a/contrib/hxt/hxt_tetSync.c
+++ b/contrib/hxt/tetMesh/src/hxt_tetSync.c
@@ -1,5 +1,14 @@
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
 #include "hxt_tetSync.h"
 #include "hxt_tetFlag.h"
+#include "hxt_tools.h"
 
 HXTStatus synchronizeReallocation(HXT2Sync* shared,
                                   int* threadFinishedLocal) {
@@ -73,7 +82,7 @@ HXTStatus createNewDeleted(HXT2Sync* shared,
   #pragma omp atomic capture
   { ntet = mesh->tetrahedra.num; mesh->tetrahedra.num+=needed;}
 
-  if(mesh->tetrahedra.num > mesh->tetrahedra.size) {
+  if(ntet + needed > mesh->tetrahedra.size) {
     HXT_CHECK( synchronizeReallocation(shared, NULL) );
   }
   HXT_CHECK( askForDeleted(deleted, needed) );
@@ -91,6 +100,7 @@ HXTStatus createNewDeleted(HXT2Sync* shared,
     }
   }
 
+  deleted->createdNew = 1;
   deleted->num = DELETED_BUFFER_SIZE;
   return HXT_STATUS_OK;
 }
\ No newline at end of file
diff --git a/contrib/hxt/hxt_tetSync.h b/contrib/hxt/tetMesh/src/hxt_tetSync.h
similarity index 87%
rename from contrib/hxt/hxt_tetSync.h
rename to contrib/hxt/tetMesh/src/hxt_tetSync.h
index 4cb90ad680..941993e0d2 100644
--- a/contrib/hxt/hxt_tetSync.h
+++ b/contrib/hxt/tetMesh/src/hxt_tetSync.h
@@ -1,5 +1,13 @@
-#ifndef _HXT_TETSYNC_
-#define _HXT_TETSYNC_
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
+#ifndef HXT_TETSYNC_H
+#define HXT_TETSYNC_H
 
 #ifdef __cplusplus
 extern "C" {
@@ -41,6 +49,7 @@ typedef struct {
 	uint64_t* array;
 	uint64_t num;
 	uint64_t size;
+  int createdNew; // just a flag that tells if createNewDeleted was called
 } HXTDeleted;
 
 
diff --git a/contrib/hxt/hxt_tetUtils.c b/contrib/hxt/tetMesh/src/hxt_tetUtils.c
similarity index 88%
rename from contrib/hxt/hxt_tetUtils.c
rename to contrib/hxt/tetMesh/src/hxt_tetUtils.c
index 6e9d980124..03fa64f613 100644
--- a/contrib/hxt/hxt_tetUtils.c
+++ b/contrib/hxt/tetMesh/src/hxt_tetUtils.c
@@ -1,15 +1,24 @@
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
 #include "hxt_tetUtils.h"
 #include "hxt_tetFlag.h"
 #include "hxt_sort.h"
 
-#define MAX(x,y) ((x)>(y) ? (x) : (y))
-
 /***********************************
  * remove deleted tetrahedra of mesh
  ***********************************/
 // TODO: a parallel technique
 HXTStatus hxtRemoveDeleted(HXTMesh* mesh)
 {
+  if(mesh->tetrahedra.num==0)
+    return HXT_STATUS_OK;
+  
   #pragma omp parallel for
   for (uint64_t i=0; i<mesh->tetrahedra.num; i++) {
     if(getDeletedFlag(mesh, i)){
diff --git a/contrib/hxt/hxt_tetUtils.h b/contrib/hxt/tetMesh/src/hxt_tetUtils.h
similarity index 86%
rename from contrib/hxt/hxt_tetUtils.h
rename to contrib/hxt/tetMesh/src/hxt_tetUtils.h
index a7861f6c2b..8f5a37c145 100644
--- a/contrib/hxt/hxt_tetUtils.h
+++ b/contrib/hxt/tetMesh/src/hxt_tetUtils.h
@@ -1,11 +1,20 @@
-#ifndef _HXT_TETUTILS_
-#define _HXT_TETUTILS_
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
+#ifndef HXT_TETUTILS_H
+#define HXT_TETUTILS_H
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 #include "hxt_mesh.h"
+#include "hxt_tools.h"
 
 /**
 * \file tetUtils.h utility for the tetrahedral mesh
diff --git a/contrib/hxt/hxt_vertices.c b/contrib/hxt/tetMesh/src/hxt_vertices.c
similarity index 99%
rename from contrib/hxt/hxt_vertices.c
rename to contrib/hxt/tetMesh/src/hxt_vertices.c
index ad5c25d386..09c34bc45a 100644
--- a/contrib/hxt/hxt_vertices.c
+++ b/contrib/hxt/tetMesh/src/hxt_vertices.c
@@ -1,3 +1,11 @@
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
 #include "hxt_omp.h"
 #include <string.h>
 #include "hxt_vertices.h"
diff --git a/contrib/hxt/hxt_vertices.h b/contrib/hxt/tetMesh/src/hxt_vertices.h
similarity index 93%
rename from contrib/hxt/hxt_vertices.h
rename to contrib/hxt/tetMesh/src/hxt_vertices.h
index e629e1b1c9..3f7176b54e 100644
--- a/contrib/hxt/hxt_vertices.h
+++ b/contrib/hxt/tetMesh/src/hxt_vertices.h
@@ -1,5 +1,13 @@
-#ifndef _HEXTREME_VERTICES_
-#define _HEXTREME_VERTICES_
+// Hxt - Copyright (C) 
+// 2016 - 2020 UCLouvain
+//
+// See the LICENSE.txt file for license information.
+//
+// Contributor(s):
+//   Célestin Marot
+
+#ifndef HXT_VERTICES_H
+#define HXT_VERTICES_H
 
 #include "hxt_mesh.h"
 #include "hxt_bbox.h"
-- 
GitLab