Salome HOME
bos #20256: [CEA 18523] Porting SMESH to int 64 bits
[plugins/blsurfplugin.git] / src / BLSURFPlugin / BLSURFPlugin_Hypothesis.cxx
index 607bf095150a81edba42ae9b12e757bb94ae8129..e69a2696fd643025180c745b0c5d1000eb5a2ac2 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2016  CEA/DEN, EDF R&D
+// Copyright (C) 2007-2021  CEA/DEN, EDF R&D
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
@@ -32,6 +32,8 @@
 #include <iostream>
 #include <sstream>
 
+#include <Basics_Utils.hxx>
+
 // cascade include
 #include "ShapeAnalysis.hxx"
 
 #include CORBA_CLIENT_HEADER(SALOMEDS)
 #include CORBA_CLIENT_HEADER(GEOM_Gen)
 
+#include <meshgems/meshgems.h>
+#define MESHGEMS_VERSION_HEX (MESHGEMS_VERSION_MAJOR << 16 | MESHGEMS_VERSION_MINOR << 8 | MESHGEMS_VERSION_PATCH)
+
+#include <boost/archive/text_oarchive.hpp>
+#include <boost/archive/text_iarchive.hpp>
+#include <boost/serialization/set.hpp>
+#include <boost/serialization/vector.hpp>
+#include <boost/serialization/string.hpp>
+
+namespace
+{
+  struct GET_DEFAULT // struct used to get default value from GetOptionValue()
+  {
+    bool isDefault;
+    operator bool* () { return &isDefault; }
+  };
+}
+
 //=============================================================================
-BLSURFPlugin_Hypothesis::BLSURFPlugin_Hypothesis(int hypId, int studyId, SMESH_Gen * gen) :
-  SMESH_Hypothesis(hypId, studyId, gen), 
+BLSURFPlugin_Hypothesis::BLSURFPlugin_Hypothesis(int hypId, SMESH_Gen * gen, bool hasgeom) :
+  SMESH_Hypothesis(hypId, gen),
   _physicalMesh(GetDefaultPhysicalMesh()),
   _geometricMesh(GetDefaultGeometricMesh()),
   _phySize(GetDefaultPhySize()),
@@ -50,21 +70,35 @@ BLSURFPlugin_Hypothesis::BLSURFPlugin_Hypothesis(int hypId, int studyId, SMESH_G
   _maxSize(GetDefaultMaxSize()),
   _minSizeRel(GetDefaultMinSizeRel()),
   _maxSizeRel(GetDefaultMaxSizeRel()),
+  _useGradation(GetDefaultUseGradation()),
   _gradation(GetDefaultGradation()),
-  _quadAllowed(GetDefaultQuadAllowed()),
+  _useVolumeGradation(GetDefaultUseVolumeGradation()),
+  _volumeGradation(GetDefaultVolumeGradation()),
+  _elementType(GetDefaultElementType()),
   _angleMesh(GetDefaultAngleMesh()),
-  _chordalError(GetDefaultChordalError()), 
+  _chordalError(GetDefaultChordalError()),
   _anisotropic(GetDefaultAnisotropic()),
   _anisotropicRatio(GetDefaultAnisotropicRatio()),
   _removeTinyEdges(GetDefaultRemoveTinyEdges()),
   _tinyEdgeLength(GetDefaultTinyEdgeLength()),
+  _optimiseTinyEdges(GetDefaultOptimiseTinyEdges()),
+  _tinyEdgeOptimisationLength(GetDefaultTinyEdgeOptimisationLength()),
+  _correctSurfaceIntersec(GetDefaultCorrectSurfaceIntersection()),
+  _corrSurfaceIntersCost(GetDefaultCorrectSurfaceIntersectionMaxCost()),
   _badElementRemoval(GetDefaultBadElementRemoval()),
   _badElementAspectRatio(GetDefaultBadElementAspectRatio()),
   _optimizeMesh(GetDefaultOptimizeMesh()),
   _quadraticMesh(GetDefaultQuadraticMesh()),
   _verb(GetDefaultVerbosity()),
   _topology(GetDefaultTopology()),
+  _useSurfaceProximity(GetDefaultUseSurfaceProximity()),
+  _nbSurfaceProximityLayers(GetDefaultNbSurfaceProximityLayers()),
+  _surfaceProximityRatio(GetDefaultSurfaceProximityRatio()),
+  _useVolumeProximity(GetDefaultUseVolumeProximity()),
+  _nbVolumeProximityLayers(GetDefaultNbVolumeProximityLayers()),
+  _volumeProximityRatio(GetDefaultVolumeProximityRatio()),
   _preCADMergeEdges(GetDefaultPreCADMergeEdges()),
+  _preCADRemoveDuplicateCADFaces(GetDefaultPreCADRemoveDuplicateCADFaces()),
   _preCADProcess3DTopology(GetDefaultPreCADProcess3DTopology()),
   _preCADDiscardInput(GetDefaultPreCADDiscardInput()),
   _sizeMap(GetDefaultSizeMap()),
@@ -82,58 +116,62 @@ BLSURFPlugin_Hypothesis::BLSURFPlugin_Hypothesis(int hypId, int studyId, SMESH_G
   _preCadEdgesPeriodicityVector(GetDefaultPreCadEdgesPeriodicityVector()),
   _GMFFileName(GetDefaultGMFFile())
 {
-  _name = GetHypType();
+  _name = GetHypType(hasgeom);
   _param_algo_dim = 2;
-  
-//   _GMFFileMode = false; // GMF ascii mode
-
-  const char* boolOptionNames[] = {         "correct_surface_intersections",            // default = 1
-                                            "create_tag_on_collision",                  // default = 1
-                                            "debug",                                    // default = 0
-                                            "enforce_cad_edge_sizes",                   // default = 0
-                                            "frontal",                                  // ok default = 1
-                                            "jacobian_rectification_respect_geometry",  // default = 1
-                                            "proximity",                                // default = 0
-                                            "rectify_jacobian",                         // default = 1
-                                            "respect_geometry",                         // default = 1
-                                            "optimise_tiny_edges",                      // default = 0
-                                            "remove_duplicate_cad_faces",               // default = 1
-                                            "tiny_edge_avoid_surface_intersections",    // default = 1
-                                            "tiny_edge_respect_geometry",               // default = 0
-                                            "" // mark of end
-      };
 
-  const char* intOptionNames[] = {          "hinterpol_flag",                           // ok default = 0
-                                            "hmean_flag",                               // ok default = 0
-                                            "max_number_of_points_per_patch",           // default = 100000
-                                            "prox_nb_layer",                            // detects the volumic proximity of surfaces
-                                            "" // mark of end
-      };
-  const char* doubleOptionNames[] = {       "surface_intersections_processing_max_cost",// default = 15
-                                            "periodic_tolerance",                       // default = diag/100
-                                            "prox_ratio",
-                                            "volume_gradation",
-                                            "tiny_edge_optimisation_length",            // default = diag * 1e-6
-                                            "" // mark of end
-      };
-  const char* charOptionNames[] = {         "required_entities",                        // default = "respect"
-                                            "tags",                                     // default = "respect"
-                                            "" // mark of end
-      };
+  // Advanced options with their defaults according to MG User Manual
+
+  const char* boolOptionNames[] = {
+#if MESHGEMS_VERSION_HEX < 0x020A00
+    "enforce_cad_edge_sizes",                   // default = 0 // Deprecated since MeshGems 2.10
+#endif
+    "jacobian_rectification_respect_geometry",  // default = 1
+    "rectify_jacobian",                         // default = 1
+    "respect_geometry",                         // default = 1
+    "tiny_edge_avoid_surface_intersections",    // default = 1
+    "debug",                                    // default = 0
+    "allow_patch_independent",                   // false
+    "" // mark of end
+  };
+
+  const char* intOptionNames[] = {
+#if MESHGEMS_VERSION_HEX < 0x020A00
+    "max_number_of_points_per_patch",           // default = 100000 // Deprecated since MeshGems 2.10
+#endif
+    "max_number_of_threads",                    // default = 4
+    "" // mark of end
+  };
+  const char* doubleOptionNames[] = {       // "surface_intersections_processing_max_cost",// default = 15
+                                            // "periodic_tolerance",                       // default = diag/100
+                                            // "volume_gradation",
+                                            // "tiny_edge_optimisation_length",            // default = diag * 1e-6
+    "" // mark of end
+  };
+  const char* charOptionNames[] = {         // "required_entities",                        // default = "respect"
+                                            // "tags",                                     // default = "respect"
+    "" // mark of end
+  };
 
   // PreCAD advanced options
   const char* preCADboolOptionNames[] = {   "closed_geometry",                          // default = 0
-                                            "create_tag_on_collision",                  // default = 1
-                                            "debug",                                    // default = 0 
-                                            "remove_tiny_edges",                        // default = 0
+                                            "discard_input_topology",                   // default = 0
+                                            "merge_edges",                              // default =  = 1
+                                            "remove_duplicate_cad_faces",               // default = 1
+                                            // "create_tag_on_collision",                  // default = 1
+                                            "process_3d_topology",                      // default = 1
+                                            // "remove_tiny_edges",                        // default = 0
+                                            // remove_tiny_uv_edges option is not documented
+                                            // but it is useful that the user can change it to disable all preprocessing options
+                                            "remove_tiny_uv_edges",                        // default = 1
+                                            "compute_ridges",                             // true
                                             "" // mark of end
       };
-  const char* preCADintOptionNames[] = {    "manifold_geometry",                        // default = 0
+  const char* preCADintOptionNames[] = {    // "manifold_geometry",                        // default = 0
                                             "" // mark of end
       };
   const char* preCADdoubleOptionNames[] = { "periodic_tolerance",                       // default = diag * 1e-5
                                             "sewing_tolerance",                         // default = diag * 5e-4
-                                            "tiny_edge_length",                         // default = diag * 1e-5
+                                            // "tiny_edge_length",                         // default = diag * 1e-5
                                             "" // mark of end
       };
   const char* preCADcharOptionNames[] = {   "required_entities",                        // default = "respect"
@@ -143,18 +181,22 @@ BLSURFPlugin_Hypothesis::BLSURFPlugin_Hypothesis(int hypId, int studyId, SMESH_G
   
   int i = 0;
   while (boolOptionNames[i][0])
+  {
+    _boolOptions.insert( boolOptionNames[i] );
     _option2value[boolOptionNames[i++]].clear();
-  
+  }
   i = 0;
-  while (preCADboolOptionNames[i][0])
+  while (preCADboolOptionNames[i][0] && hasgeom)
+  {
+    _boolOptions.insert( preCADboolOptionNames[i] );
     _preCADoption2value[preCADboolOptionNames[i++]].clear();
-  
+  }
   i = 0;
   while (intOptionNames[i][0])
     _option2value[intOptionNames[i++]].clear();
   
   i = 0;
-  while (preCADintOptionNames[i][0])
+  while (preCADintOptionNames[i][0] && hasgeom)
     _preCADoption2value[preCADintOptionNames[i++]].clear();
 
   i = 0;
@@ -163,7 +205,7 @@ BLSURFPlugin_Hypothesis::BLSURFPlugin_Hypothesis(int hypId, int studyId, SMESH_G
     _option2value[doubleOptionNames[i++]].clear();
   }
   i = 0;
-  while (preCADdoubleOptionNames[i][0]) {
+  while (preCADdoubleOptionNames[i][0] && hasgeom) {
     _preCADdoubleOptions.insert(preCADdoubleOptionNames[i]);
     _preCADoption2value[preCADdoubleOptionNames[i++]].clear();
   }
@@ -173,50 +215,85 @@ BLSURFPlugin_Hypothesis::BLSURFPlugin_Hypothesis(int hypId, int studyId, SMESH_G
     _option2value[charOptionNames[i++]].clear();
   }
   i = 0;
-  while (preCADcharOptionNames[i][0]) {
+  while (preCADcharOptionNames[i][0] && hasgeom) {
     _preCADcharOptions.insert(preCADcharOptionNames[i]);
     _preCADoption2value[preCADcharOptionNames[i++]].clear();
   }
-  
 
-      
-  _sizeMap.clear();
-  _attractors.clear();
-  _faceEntryEnfVertexListMap.clear();
-  _enfVertexList.clear();
-  _faceEntryCoordsListMap.clear();
-  _coordsEnfVertexMap.clear();
-  _faceEntryEnfVertexEntryListMap.clear();
-  _enfVertexEntryEnfVertexMap.clear();
-  _groupNameNodeIDMap.clear();
+  // default values to be used while MG meshing
+
+#if MESHGEMS_VERSION_HEX < 0x020A00
+  _defaultOptionValues["enforce_cad_edge_sizes"                 ] = "no";  // Deprecated since MeshGems 2.10
+#endif
+  _defaultOptionValues["jacobian_rectification_respect_geometry"] = "yes";
+#if MESHGEMS_VERSION_HEX < 0x020A00
+  _defaultOptionValues["max_number_of_points_per_patch"         ] = "0";   // Deprecated since MeshGems 2.10
+#endif
+  _defaultOptionValues["max_number_of_threads"                  ] = "4";
+  _defaultOptionValues["rectify_jacobian"                       ] = "yes";
+  _defaultOptionValues["respect_geometry"                       ] = "yes";
+  _defaultOptionValues["tiny_edge_avoid_surface_intersections"  ] = "yes";
+  //_defaultOptionValues["use_deprecated_patch_mesher"          ] = "no";
+  _defaultOptionValues["debug"                                  ] = "no";
+  _defaultOptionValues["allow_patch_independent"                ] = "no";
+  if ( hasgeom )
+  {
+    _defaultOptionValues["closed_geometry"                        ] = "no";
+    _defaultOptionValues["discard_input_topology"                 ] = "no";
+    _defaultOptionValues["merge_edges"                            ] = "no";
+    _defaultOptionValues["periodic_tolerance"                     ] = "1e-5*D";
+    _defaultOptionValues["process_3d_topology"                    ] = "no";
+    _defaultOptionValues["remove_duplicate_cad_faces"             ] = "no";
+    _defaultOptionValues["remove_tiny_uv_edges"                   ] = "no";
+    _defaultOptionValues["required_entities"                      ] = "respect";
+    _defaultOptionValues["sewing_tolerance"                       ] = "5e-4*D";
+    _defaultOptionValues["tags"                                   ] = "respect";
+    _defaultOptionValues["compute_ridges"                         ] = "yes";
+  }
+
+  if ( MESHGEMS_VERSION_HEX < 0x020906 )
+  {
+    std::string missingOption = "allow_patch_independent";
+    _defaultOptionValues.erase( missingOption );
+    _boolOptions.erase( missingOption );
+    _option2value.erase( missingOption );
+  }
+
+#ifdef _DEBUG_
+  // check validity of option names of _defaultOptionValues
+  TOptionValues::iterator n2v = _defaultOptionValues.begin();
+  for ( ; n2v != _defaultOptionValues.end(); ++n2v )
+    ASSERT( _option2value.count( n2v->first ) || _preCADoption2value.count( n2v->first ));
+  ASSERT( _option2value.size() + _preCADoption2value.size() == _defaultOptionValues.size() );
+#endif
 
-  /* TODO GROUPS
-   _groupNameEnfVertexListMap.clear();
-   _enfVertexGroupNameMap.clear();
-   */
 }
 
 TopoDS_Shape BLSURFPlugin_Hypothesis::entryToShape(std::string entry)
 {
-  MESSAGE("BLSURFPlugin_Hypothesis::entryToShape "<<entry );
   GEOM::GEOM_Object_var aGeomObj;
-  SMESH_Gen_i* smeshGen_i = SMESH_Gen_i::GetSMESHGen();
-  SALOMEDS::Study_ptr myStudy = smeshGen_i->GetCurrentStudy();
   
   TopoDS_Shape S = TopoDS_Shape();
-  SALOMEDS::SObject_var aSObj = myStudy->FindObjectID( entry.c_str() );
+  SALOMEDS::SObject_var aSObj = SMESH_Gen_i::GetSMESHGen()->getStudyServant()->FindObjectID( entry.c_str() );
   if (!aSObj->_is_nil() ) {
     CORBA::Object_var obj = aSObj->GetObject();
     aGeomObj = GEOM::GEOM_Object::_narrow(obj);
     aSObj->UnRegister();
   }
   if ( !aGeomObj->_is_nil() )
-    S = smeshGen_i->GeomObjectToShape( aGeomObj.in() );
+    S = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( aGeomObj.in() );
   return S;
 }
 
 //=============================================================================
-void BLSURFPlugin_Hypothesis::SetPhysicalMesh(PhysicalMesh thePhysicalMesh) {
+std::string BLSURFPlugin_Hypothesis::GetMeshGemsVersion()
+{
+  return MESHGEMS_VERSION_LONG;
+}
+
+//=============================================================================
+void BLSURFPlugin_Hypothesis::SetPhysicalMesh(PhysicalMesh thePhysicalMesh)
+{
   if (thePhysicalMesh != _physicalMesh) {
     _physicalMesh = thePhysicalMesh;
     NotifySubMeshesHypothesisModification();
@@ -224,7 +301,8 @@ void BLSURFPlugin_Hypothesis::SetPhysicalMesh(PhysicalMesh thePhysicalMesh) {
 }
 
 //=============================================================================
-void BLSURFPlugin_Hypothesis::SetGeometricMesh(GeometricMesh theGeometricMesh) {
+void BLSURFPlugin_Hypothesis::SetGeometricMesh(GeometricMesh theGeometricMesh)
+{
   if (theGeometricMesh != _geometricMesh) {
     _geometricMesh = theGeometricMesh;
 //     switch (_geometricMesh) {
@@ -239,12 +317,12 @@ void BLSURFPlugin_Hypothesis::SetGeometricMesh(GeometricMesh theGeometricMesh) {
 }
 
 //=============================================================================
-void BLSURFPlugin_Hypothesis::SetPhySize(double theVal, bool isRelative) {
+void BLSURFPlugin_Hypothesis::SetPhySize(double theVal, bool isRelative)
+{
   if ((theVal != _phySize) || (isRelative != _phySizeRel)) {
     _phySizeRel = isRelative;
     if (theVal == 0) {
       _phySize = GetMaxSize();
-      MESSAGE("Warning: nul physical size is not allowed");
     }
     else
       _phySize = theVal;
@@ -253,7 +331,8 @@ void BLSURFPlugin_Hypothesis::SetPhySize(double theVal, bool isRelative) {
 }
 
 //=============================================================================
-void BLSURFPlugin_Hypothesis::SetMinSize(double theMinSize, bool isRelative) {
+void BLSURFPlugin_Hypothesis::SetMinSize(double theMinSize, bool isRelative)
+{
   if ((theMinSize != _minSize) || (isRelative != _minSizeRel)) {
     _minSizeRel = isRelative;
     _minSize = theMinSize;
@@ -262,7 +341,8 @@ void BLSURFPlugin_Hypothesis::SetMinSize(double theMinSize, bool isRelative) {
 }
 
 //=============================================================================
-void BLSURFPlugin_Hypothesis::SetMaxSize(double theMaxSize, bool isRelative) {
+void BLSURFPlugin_Hypothesis::SetMaxSize(double theMaxSize, bool isRelative)
+{
   if ((theMaxSize != _maxSize) || (isRelative != _maxSizeRel)) {
     _maxSizeRel = isRelative;
     _maxSize = theMaxSize;
@@ -271,7 +351,18 @@ void BLSURFPlugin_Hypothesis::SetMaxSize(double theMaxSize, bool isRelative) {
 }
 
 //=============================================================================
-void BLSURFPlugin_Hypothesis::SetGradation(double theVal) {
+void BLSURFPlugin_Hypothesis::SetUseGradation(bool theVal)
+{
+  if (theVal != _useGradation) {
+    _useGradation = theVal;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+void BLSURFPlugin_Hypothesis::SetGradation(double theVal)
+{
+  _useGradation = ( theVal > 0 );
   if (theVal != _gradation) {
     _gradation = theVal;
     NotifySubMeshesHypothesisModification();
@@ -279,15 +370,36 @@ void BLSURFPlugin_Hypothesis::SetGradation(double theVal) {
 }
 
 //=============================================================================
-void BLSURFPlugin_Hypothesis::SetQuadAllowed(bool theVal) {
-  if (theVal != _quadAllowed) {
-    _quadAllowed = theVal;
+void BLSURFPlugin_Hypothesis::SetUseVolumeGradation(bool theVal)
+{
+  if (theVal != _useVolumeGradation) {
+    _useVolumeGradation = theVal;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+void BLSURFPlugin_Hypothesis::SetVolumeGradation(double theVal)
+{
+  _useVolumeGradation = ( theVal > 0 );
+  if (theVal != _volumeGradation) {
+    _volumeGradation = theVal;
     NotifySubMeshesHypothesisModification();
   }
 }
 
 //=============================================================================
-void BLSURFPlugin_Hypothesis::SetAngleMesh(double theVal) {
+void BLSURFPlugin_Hypothesis::SetElementType(ElementType theElementType)
+{
+  if (theElementType != _elementType) {
+    _elementType = theElementType;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+void BLSURFPlugin_Hypothesis::SetAngleMesh(double theVal)
+{
   if (theVal != _angleMesh) {
     _angleMesh = theVal;
     NotifySubMeshesHypothesisModification();
@@ -295,7 +407,8 @@ void BLSURFPlugin_Hypothesis::SetAngleMesh(double theVal) {
 }
 
 //=============================================================================
-void BLSURFPlugin_Hypothesis::SetChordalError(double theDistance) {
+void BLSURFPlugin_Hypothesis::SetChordalError(double theDistance)
+{
   if (theDistance != _chordalError) {
     _chordalError = theDistance;
     NotifySubMeshesHypothesisModification();
@@ -303,7 +416,8 @@ void BLSURFPlugin_Hypothesis::SetChordalError(double theDistance) {
 }
 
 //=============================================================================
-void BLSURFPlugin_Hypothesis::SetAnisotropic(bool theVal) {
+void BLSURFPlugin_Hypothesis::SetAnisotropic(bool theVal)
+{
   if (theVal != _anisotropic) {
     _anisotropic = theVal;
     NotifySubMeshesHypothesisModification();
@@ -311,7 +425,8 @@ void BLSURFPlugin_Hypothesis::SetAnisotropic(bool theVal) {
 }
 
 //=============================================================================
-void BLSURFPlugin_Hypothesis::SetAnisotropicRatio(double theVal) {
+void BLSURFPlugin_Hypothesis::SetAnisotropicRatio(double theVal)
+{
   if (theVal != _anisotropicRatio) {
     _anisotropicRatio = theVal;
     NotifySubMeshesHypothesisModification();
@@ -319,7 +434,8 @@ void BLSURFPlugin_Hypothesis::SetAnisotropicRatio(double theVal) {
 }
 
 //=============================================================================
-void BLSURFPlugin_Hypothesis::SetRemoveTinyEdges(bool theVal) {
+void BLSURFPlugin_Hypothesis::SetRemoveTinyEdges(bool theVal)
+{
   if (theVal != _removeTinyEdges) {
     _removeTinyEdges = theVal;
     NotifySubMeshesHypothesisModification();
@@ -327,7 +443,8 @@ void BLSURFPlugin_Hypothesis::SetRemoveTinyEdges(bool theVal) {
 }
 
 //=============================================================================
-void BLSURFPlugin_Hypothesis::SetTinyEdgeLength(double theVal) {
+void BLSURFPlugin_Hypothesis::SetTinyEdgeLength(double theVal)
+{
   if (theVal != _tinyEdgeLength) {
     _tinyEdgeLength = theVal;
     NotifySubMeshesHypothesisModification();
@@ -335,7 +452,44 @@ void BLSURFPlugin_Hypothesis::SetTinyEdgeLength(double theVal) {
 }
 
 //=============================================================================
-void BLSURFPlugin_Hypothesis::SetBadElementRemoval(bool theVal) {
+void BLSURFPlugin_Hypothesis::SetOptimiseTinyEdges(bool theVal)
+{
+  if (theVal != _optimiseTinyEdges) {
+    _optimiseTinyEdges = theVal;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+void BLSURFPlugin_Hypothesis::SetTinyEdgeOptimisationLength(double theVal)
+{
+  if (theVal != _tinyEdgeOptimisationLength) {
+    _tinyEdgeOptimisationLength = theVal;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+void BLSURFPlugin_Hypothesis::SetCorrectSurfaceIntersection(bool theVal)
+{
+  if (theVal != _correctSurfaceIntersec) {
+    _correctSurfaceIntersec = theVal;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+void BLSURFPlugin_Hypothesis::SetCorrectSurfaceIntersectionMaxCost(double theVal)
+{
+  if (theVal != _corrSurfaceIntersCost) {
+    _corrSurfaceIntersCost = theVal;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+void BLSURFPlugin_Hypothesis::SetBadElementRemoval(bool theVal)
+{
   if (theVal != _badElementRemoval) {
     _badElementRemoval = theVal;
     NotifySubMeshesHypothesisModification();
@@ -343,7 +497,8 @@ void BLSURFPlugin_Hypothesis::SetBadElementRemoval(bool theVal) {
 }
 
 //=============================================================================
-void BLSURFPlugin_Hypothesis::SetBadElementAspectRatio(double theVal) {
+void BLSURFPlugin_Hypothesis::SetBadElementAspectRatio(double theVal)
+{
   if (theVal != _badElementAspectRatio) {
     _badElementAspectRatio = theVal;
     NotifySubMeshesHypothesisModification();
@@ -351,7 +506,8 @@ void BLSURFPlugin_Hypothesis::SetBadElementAspectRatio(double theVal) {
 }
 
 //=============================================================================
-void BLSURFPlugin_Hypothesis::SetOptimizeMesh(bool theVal) {
+void BLSURFPlugin_Hypothesis::SetOptimizeMesh(bool theVal)
+{
   if (theVal != _optimizeMesh) {
     _optimizeMesh = theVal;
     NotifySubMeshesHypothesisModification();
@@ -359,7 +515,8 @@ void BLSURFPlugin_Hypothesis::SetOptimizeMesh(bool theVal) {
 }
 
 //=============================================================================
-void BLSURFPlugin_Hypothesis::SetQuadraticMesh(bool theVal) {
+void BLSURFPlugin_Hypothesis::SetQuadraticMesh(bool theVal)
+{
   if (theVal != _quadraticMesh) {
     _quadraticMesh = theVal;
     NotifySubMeshesHypothesisModification();
@@ -367,13 +524,74 @@ void BLSURFPlugin_Hypothesis::SetQuadraticMesh(bool theVal) {
 }
 
 //=============================================================================
-void BLSURFPlugin_Hypothesis::SetTopology(Topology theTopology) {
+void BLSURFPlugin_Hypothesis::SetTopology(Topology theTopology)
+{
   if (theTopology != _topology) {
     _topology = theTopology;
     NotifySubMeshesHypothesisModification();
   }
 }
 
+//=============================================================================
+void BLSURFPlugin_Hypothesis::SetUseSurfaceProximity( bool toUse )
+{
+  if ( _useSurfaceProximity != toUse )
+  {
+    _useSurfaceProximity = toUse;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+void BLSURFPlugin_Hypothesis::SetNbSurfaceProximityLayers( int nbLayers )
+{
+  if ( _nbSurfaceProximityLayers != nbLayers )
+  {
+    _nbSurfaceProximityLayers = nbLayers;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+void BLSURFPlugin_Hypothesis::SetSurfaceProximityRatio( double ratio )
+{
+  if ( _surfaceProximityRatio != ratio )
+  {
+    _surfaceProximityRatio = ratio;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+void BLSURFPlugin_Hypothesis::SetUseVolumeProximity( bool toUse )
+{
+  if ( _useVolumeProximity != toUse )
+  {
+    _useVolumeProximity = toUse;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+void BLSURFPlugin_Hypothesis::SetNbVolumeProximityLayers( int nbLayers )
+{
+  if ( _nbVolumeProximityLayers != nbLayers )
+  {
+    _nbVolumeProximityLayers = nbLayers;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+void BLSURFPlugin_Hypothesis::SetVolumeProximityRatio( double ratio )
+{
+  if ( _volumeProximityRatio != ratio )
+  {
+    _volumeProximityRatio = ratio;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
 //=============================================================================
 void BLSURFPlugin_Hypothesis::SetVerbosity(int theVal) {
   if (theVal != _verb) {
@@ -383,55 +601,473 @@ void BLSURFPlugin_Hypothesis::SetVerbosity(int theVal) {
 }
 
 //=============================================================================
-void BLSURFPlugin_Hypothesis::SetPreCADMergeEdges(bool theVal) {
-  if (theVal != _preCADMergeEdges) {
-//     SetTopology(PreCAD);
+void BLSURFPlugin_Hypothesis::SetEnforceCadEdgesSize( bool toEnforce )
+{
+#if MESHGEMS_VERSION_HEX < 0x020A00
+  // Deprecated since MeshGems 2.10
+  if ( GetEnforceCadEdgesSize() != toEnforce )
+  {
+    SetOptionValue( "enforce_cad_edge_sizes", toEnforce ? "yes" : "no" );
+    NotifySubMeshesHypothesisModification();
+  }
+#else
+  (void)toEnforce; // maybe unused
+#endif
+}
+//=============================================================================
+bool BLSURFPlugin_Hypothesis::GetEnforceCadEdgesSize()
+{
+#if MESHGEMS_VERSION_HEX < 0x020A00
+  // Deprecated since MeshGems 2.10
+  return ToBool( GetOptionValue( "enforce_cad_edge_sizes" ), GET_DEFAULT() );
+#else
+  return false;
+#endif
+}
+//=============================================================================
+
+void BLSURFPlugin_Hypothesis::SetJacobianRectificationRespectGeometry( bool allowRectification )
+{
+  if ( GetJacobianRectificationRespectGeometry() != allowRectification )
+  {
+    SetOptionValue("jacobian_rectification_respect_geometry", allowRectification ? "yes" : "no" );
+    NotifySubMeshesHypothesisModification();
+  }
+}
+//=============================================================================
+bool BLSURFPlugin_Hypothesis::GetJacobianRectificationRespectGeometry()
+{
+  return ToBool( GetOptionValue("jacobian_rectification_respect_geometry", GET_DEFAULT()));
+}
+//=============================================================================
+
+void BLSURFPlugin_Hypothesis::SetJacobianRectification( bool allowRectification )
+{
+  if ( GetJacobianRectification() != allowRectification )
+  {
+    SetOptionValue( "rectify_jacobian", allowRectification ? "yes" : "no" );
+    NotifySubMeshesHypothesisModification();
+  }
+}
+//=============================================================================
+bool BLSURFPlugin_Hypothesis::GetJacobianRectification()
+{
+  return ToBool( GetOptionValue("rectify_jacobian", GET_DEFAULT()));
+}
+//=============================================================================
+
+void BLSURFPlugin_Hypothesis::SetUseDeprecatedPatchMesher( bool /*useDeprecatedPatchMesher*/ )
+{
+  // if ( GetUseDeprecatedPatchMesher() != useDeprecatedPatchMesher )
+  // {
+  //   SetOptionValue( "use_deprecated_patch_mesher", useDeprecatedPatchMesher ? "yes" : "no" );
+  //   NotifySubMeshesHypothesisModification();
+  // }
+}
+//=============================================================================
+bool BLSURFPlugin_Hypothesis::GetUseDeprecatedPatchMesher()
+{
+  return false;//ToBool( GetOptionValue("use_deprecated_patch_mesher", GET_DEFAULT()));
+}
+//=============================================================================
+
+void BLSURFPlugin_Hypothesis::SetMaxNumberOfPointsPerPatch( int nb )
+{
+#if MESHGEMS_VERSION_HEX < 0x020A00
+  // Deprecated since MeshGems 2.10
+  if ( nb < 0 )
+    throw std::invalid_argument( SMESH_Comment("Invalid number of points: ") << nb );
+
+  if ( GetMaxNumberOfPointsPerPatch() != nb )
+  {
+    SetOptionValue("max_number_of_points_per_patch", SMESH_Comment( nb ));
+    NotifySubMeshesHypothesisModification();
+  }
+#else
+  (void)nb; // maybe unused
+#endif
+}
+//=============================================================================
+int BLSURFPlugin_Hypothesis::GetMaxNumberOfPointsPerPatch()
+{
+#if MESHGEMS_VERSION_HEX < 0x020A00
+  // Deprecated since MeshGems 2.10
+  return ToInt( GetOptionValue("max_number_of_points_per_patch", GET_DEFAULT()));
+#else
+  return 0;
+#endif
+}
+//=============================================================================
+
+void BLSURFPlugin_Hypothesis::SetMaxNumberOfThreads( int nb )
+{
+  if ( nb < 0 )
+    throw std::invalid_argument( SMESH_Comment("Invalid number of threads: ") << nb );
+
+  if ( GetMaxNumberOfThreads() != nb )
+  {
+    SetOptionValue("max_number_of_threads", SMESH_Comment( nb ));
+    NotifySubMeshesHypothesisModification();
+  }
+}
+//=============================================================================
+int BLSURFPlugin_Hypothesis::GetMaxNumberOfThreads()
+{
+  return ToInt( GetOptionValue("max_number_of_threads", GET_DEFAULT()));
+}
+//=============================================================================
+
+void BLSURFPlugin_Hypothesis::SetRespectGeometry( bool toRespect )
+{
+  if ( GetRespectGeometry() != toRespect )
+  {
+    SetOptionValue("respect_geometry", toRespect ? "yes" : "no" );
+    NotifySubMeshesHypothesisModification();
+  }
+}
+//=============================================================================
+bool BLSURFPlugin_Hypothesis::GetRespectGeometry()
+{
+  return ToBool( GetOptionValue( "respect_geometry", GET_DEFAULT()));
+}
+//=============================================================================
+
+void BLSURFPlugin_Hypothesis::SetTinyEdgesAvoidSurfaceIntersections( bool toAvoidIntersection )
+{
+  if ( GetTinyEdgesAvoidSurfaceIntersections() != toAvoidIntersection )
+  {
+    SetOptionValue("tiny_edge_avoid_surface_intersections", toAvoidIntersection ? "yes" : "no" );
+    NotifySubMeshesHypothesisModification();
+  }
+}
+//=============================================================================
+bool BLSURFPlugin_Hypothesis::GetTinyEdgesAvoidSurfaceIntersections()
+{
+  return ToBool( GetOptionValue("tiny_edge_avoid_surface_intersections", GET_DEFAULT()));
+}
+//=============================================================================
+
+void BLSURFPlugin_Hypothesis::SetClosedGeometry( bool isClosed )
+{
+  if ( GetClosedGeometry() != isClosed )
+  {
+    SetPreCADOptionValue("closed_geometry", isClosed ? "yes" : "no" );
+    NotifySubMeshesHypothesisModification();
+  }
+}
+//=============================================================================
+bool BLSURFPlugin_Hypothesis::GetClosedGeometry()
+{
+  return ToBool( GetPreCADOptionValue( "closed_geometry", GET_DEFAULT()));
+}
+//=============================================================================
+
+void BLSURFPlugin_Hypothesis::SetDebug( bool isDebug )
+{
+  if ( GetDebug() != isDebug )
+  {
+    SetPreCADOptionValue("debug", isDebug ? "yes" : "no" );
+    NotifySubMeshesHypothesisModification();
+  }
+}
+//=============================================================================
+bool BLSURFPlugin_Hypothesis::GetDebug()
+{
+  return ToBool( GetPreCADOptionValue("debug", GET_DEFAULT()));
+}
+//=============================================================================
+
+void BLSURFPlugin_Hypothesis::SetPeriodicTolerance( CORBA::Double tol )
+{
+  if ( tol <= 0 )
+    throw std::invalid_argument( SMESH_Comment("Invalid tolerance: ") << tol );
+  if ( GetPeriodicTolerance() != tol )
+  {
+    SetPreCADOptionValue("periodic_tolerance", SMESH_Comment( tol ) );
+    NotifySubMeshesHypothesisModification();
+  }
+}
+//=============================================================================
+double BLSURFPlugin_Hypothesis::GetPeriodicTolerance()
+{
+  return ToDbl( GetPreCADOptionValue( "periodic_tolerance", GET_DEFAULT()));
+}
+//=============================================================================
+
+void BLSURFPlugin_Hypothesis::SetRequiredEntities( const std::string& howToTreat )
+{
+  if ( howToTreat != "respect" && howToTreat != "ignore" && howToTreat != "clear"  )
+    throw std::invalid_argument
+      ( SMESH_Comment("required_entities must be in ['respect','ignore','clear'] "));
+
+  if ( GetRequiredEntities() != howToTreat )
+  {
+    SetPreCADOptionValue("required_entities", howToTreat );
+    NotifySubMeshesHypothesisModification();
+  }
+}
+//=============================================================================
+std::string BLSURFPlugin_Hypothesis::GetRequiredEntities()
+{
+  return GetPreCADOptionValue("required_entities", GET_DEFAULT());
+}
+//=============================================================================
+
+void BLSURFPlugin_Hypothesis::SetSewingTolerance( CORBA::Double tol )
+{
+  if ( tol <= 0 )
+    throw std::invalid_argument( SMESH_Comment("Invalid tolerance: ") << tol );
+  if ( GetSewingTolerance() != tol )
+  {
+    SetPreCADOptionValue("sewing_tolerance", SMESH_Comment( tol ) );
+    NotifySubMeshesHypothesisModification();
+  }
+}
+//=============================================================================
+CORBA::Double BLSURFPlugin_Hypothesis::GetSewingTolerance()
+{
+  return ToDbl( GetPreCADOptionValue("sewing_tolerance", GET_DEFAULT()));
+}
+//=============================================================================
+
+void BLSURFPlugin_Hypothesis::SetTags( const std::string& howToTreat )
+{
+  if ( howToTreat != "respect" && howToTreat != "ignore" && howToTreat != "clear"  )
+    throw std::invalid_argument
+      ( SMESH_Comment("'tags' must be in ['respect','ignore','clear'] "));
+
+  if ( GetTags() != howToTreat )
+  {
+    SetPreCADOptionValue("tags", howToTreat );
+    NotifySubMeshesHypothesisModification();
+  }
+}
+//=============================================================================
+std::string BLSURFPlugin_Hypothesis::GetTags()
+{
+  return GetPreCADOptionValue("tags", GET_DEFAULT());
+}
+
+//=============================================================================
+void BLSURFPlugin_Hypothesis::SetHyperPatches(const THyperPatchList& hpl, bool notifyMesh)
+{
+  if ( hpl != _hyperPatchList )
+  {
+    // join patches sharing tags
+    _hyperPatchList.clear();
+    for ( size_t i = 0; i < hpl.size(); ++i )
+    {
+      const THyperPatchTags& tags = hpl[i];
+      if ( tags.size() < 2 ) continue;
+
+      std::set<int> iPatches;
+      if ( !_hyperPatchList.empty() )
+      {
+        THyperPatchTags::iterator t = tags.begin();
+        for ( ; t != tags.end(); ++t )
+        {
+          int iPatch = -1;
+          GetHyperPatchTag( *t, this, &iPatch );
+          if ( iPatch >= 0 )
+            iPatches.insert( iPatch );
+        }
+      }
+
+      if ( iPatches.empty() )
+      {
+        _hyperPatchList.push_back( tags );
+      }
+      else
+      {
+        std::set<int>::iterator iPatch = iPatches.begin();
+        THyperPatchTags&     mainPatch = _hyperPatchList[ *iPatch ];
+        mainPatch.insert( tags.begin(), tags.end() );
+
+        for ( ++iPatch; iPatch != iPatches.end(); ++iPatch )
+        {
+          mainPatch.insert( _hyperPatchList[ *iPatch ].begin(), _hyperPatchList[ *iPatch ].end() );
+          _hyperPatchList[ *iPatch ].clear();
+        }
+        if ( iPatches.size() > 1 )
+          for ( int j = (int) _hyperPatchList.size()-1; j > 0; --j )
+            if ( _hyperPatchList[j].empty() )
+              _hyperPatchList.erase( _hyperPatchList.begin() + j );
+      }
+    }
+    if ( notifyMesh )
+      NotifySubMeshesHypothesisModification();
+  }
+}
+//=============================================================================
+void BLSURFPlugin_Hypothesis::SetHyperPatches(const THyperPatchEntriesList& hpel)
+{
+  if ( hpel != _hyperPatchEntriesList )
+  {
+    _hyperPatchEntriesList = hpel;
+    _hyperPatchList.clear();
+
+    NotifySubMeshesHypothesisModification();
+  }
+}
+//================================================================================
+/*!
+ * \brief Set _hyperPatchList by _hyperPatchEntriesList
+ */
+//================================================================================
+
+void BLSURFPlugin_Hypothesis::
+SetHyperPatchIDsByEntry( const TopoDS_Shape&                          mainShape,
+                         const std::map< std::string, TopoDS_Shape >& entryToShape)
+{
+  _hyperPatchList.clear();
+  if ( _hyperPatchEntriesList.empty() || mainShape.IsNull() )
+    return;
+
+  _hyperPatchList.resize( _hyperPatchEntriesList.size() );
+
+  TopTools_IndexedMapOfShape shapeMap;
+  TopExp::MapShapes( mainShape, shapeMap );
+
+  for ( size_t i = 0; i < _hyperPatchEntriesList.size(); ++i )
+  {
+    THyperPatchTags &            idsList = _hyperPatchList       [ i ];
+    const THyperPatchEntries & entryList = _hyperPatchEntriesList[ i ];
+    for ( const std::string & entry : entryList )
+    {
+      auto e2sIt = entryToShape.find( entry );
+      if ( e2sIt != entryToShape.end() )
+      {
+        for ( TopExp_Explorer fExp( e2sIt->second, TopAbs_FACE ); fExp.More(); fExp.Next() )
+        {
+          int id = shapeMap.FindIndex( fExp.Current() );
+          if ( id > 0 )
+            idsList.insert( id );
+        }
+      }
+    }
+  }
+  THyperPatchList hpl;
+  hpl.swap( _hyperPatchList );
+  SetHyperPatches( hpl, /*notifyMesh=*/false );
+}
+
+//=============================================================================
+/*!
+ * \brief Return a tag of a face taking into account the hyper-patches. Optionally
+ *        return an index of a patch including the face
+ */
+//================================================================================
+
+int BLSURFPlugin_Hypothesis::GetHyperPatchTag( const int                      faceTag,
+                                               const BLSURFPlugin_Hypothesis* hyp,
+                                               int*                           iPatch)
+{
+  if ( hyp )
+  {
+    const THyperPatchList& hpl = hyp->_hyperPatchList;
+    for ( size_t i = 0; i < hpl.size(); ++i )
+      if ( hpl[i].count( faceTag ))
+      {
+        if ( iPatch ) *iPatch = (int) i;
+        return *( hpl[i].begin() );
+      }
+  }
+  return faceTag;
+}
+//=============================================================================
+void BLSURFPlugin_Hypothesis::SetPreCADMergeEdges(bool theVal)
+{
+  if (theVal != ToBool( GetPreCADOptionValue("merge_edges", GET_DEFAULT()))) {
     _preCADMergeEdges = theVal;
+    SetPreCADOptionValue("merge_edges", theVal ? "yes" : "no" );
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+void BLSURFPlugin_Hypothesis::SetPreCADRemoveDuplicateCADFaces(bool theVal)
+{
+  if (theVal != ToBool( GetPreCADOptionValue("remove_duplicate_cad_faces", GET_DEFAULT()))) {
+    _preCADRemoveDuplicateCADFaces = theVal;
+    SetPreCADOptionValue("remove_duplicate_cad_faces", theVal ? "yes" : "no" );
     NotifySubMeshesHypothesisModification();
   }
 }
 
 //=============================================================================
-void BLSURFPlugin_Hypothesis::SetPreCADProcess3DTopology(bool theVal) {
-  if (theVal != _preCADProcess3DTopology) {
-//     SetTopology(PreCAD);
+void BLSURFPlugin_Hypothesis::SetPreCADProcess3DTopology(bool theVal)
+{
+  if (theVal != ToBool( GetPreCADOptionValue("process_3d_topology", GET_DEFAULT()))) {
     _preCADProcess3DTopology = theVal;
+    SetPreCADOptionValue("process_3d_topology", theVal ? "yes" : "no" );
     NotifySubMeshesHypothesisModification();
   }
 }
 
 //=============================================================================
-void BLSURFPlugin_Hypothesis::SetPreCADDiscardInput(bool theVal) {
-  if (theVal != _preCADDiscardInput) {
-//     SetTopology(PreCAD);
+void BLSURFPlugin_Hypothesis::SetPreCADDiscardInput(bool theVal)
+{
+  if (theVal != ToBool( GetPreCADOptionValue("discard_input_topology", GET_DEFAULT()))) {
     _preCADDiscardInput = theVal;
+    SetPreCADOptionValue("discard_input_topology", theVal ? "yes" : "no" );
     NotifySubMeshesHypothesisModification();
   }
 }
 
+//=============================================================================
+// Return true if any PreCAD option is activated
+bool BLSURFPlugin_Hypothesis::HasPreCADOptions(const BLSURFPlugin_Hypothesis* hyp)
+{
+  if ( !hyp || hyp->_name == GetHypType(/*hasgeom=*/false))
+  {
+    return false;
+  }
+  bool orDefault, isOk;
+  return ( ToBool( hyp->GetPreCADOptionValue("closed_geometry"           , &orDefault )) ||
+           ToBool( hyp->GetPreCADOptionValue("discard_input_topology"    , &orDefault )) ||
+           ToBool( hyp->GetPreCADOptionValue("merge_edges"               , &orDefault )) ||
+           ToBool( hyp->GetPreCADOptionValue("remove_duplicate_cad_faces", &orDefault )) ||
+           ToBool( hyp->GetPreCADOptionValue("process_3d_topology"       , &orDefault )) ||
+           ToBool( hyp->GetPreCADOption     ("manifold_geometry")        , &isOk       ) ||
+           hyp->GetPreCADOptionValue("sewing_tolerance", &orDefault ) != "5e-4*D"        ||
+           !hyp->_preCadFacesPeriodicityVector.empty()                                   ||
+           !hyp->_preCadEdgesPeriodicityVector.empty()                                   ||
+           !hyp->_facesPeriodicityVector.empty()                                         ||
+           !hyp->_edgesPeriodicityVector.empty()                                         ||
+           !hyp->_verticesPeriodicityVector.empty()                                      ||
+           !hyp->GetHyperPatches().empty()                                               ||
+           hyp->GetTopology() != FromCAD );
+}
+
 //=============================================================================
 // void BLSURFPlugin_Hypothesis::SetGMFFile(const std::string& theFileName, bool isBinary)
 void BLSURFPlugin_Hypothesis::SetGMFFile(const std::string& theFileName)
 {
   _GMFFileName = theFileName;
-//   _GMFFileMode = isBinary;
+  //   _GMFFileMode = isBinary;
   NotifySubMeshesHypothesisModification();
 }
 
 //=============================================================================
 void BLSURFPlugin_Hypothesis::SetOptionValue(const std::string& optionName, const std::string& optionValue)
-    throw (std::invalid_argument) {
+{
   TOptionValues::iterator op_val = _option2value.find(optionName);
-  if (op_val == _option2value.end()) {
-    std::string msg = "Unknown MG-CADSurf option: '" + optionName + "'";
-    throw std::invalid_argument(msg);
+  if (op_val == _option2value.end())
+  {
+    op_val = _preCADoption2value.find(optionName);
+    if (op_val == _preCADoption2value.end())
+    {
+      std::string msg = "Unknown MG-CADSurf option: '" + optionName + "'. Try SetAdvancedOption()";
+      throw std::invalid_argument(msg);
+    }
   }
-  if (op_val->second != optionValue) {
+  if (op_val->second != optionValue)
+  {
     const char* ptr = optionValue.c_str();
     // strip white spaces
     while (ptr[0] == ' ')
       ptr++;
-    int i = strlen(ptr);
+    size_t i = strlen(ptr);
     while (i != 0 && ptr[i - 1] == ' ')
       i--;
     // check value type
@@ -439,44 +1075,53 @@ void BLSURFPlugin_Hypothesis::SetOptionValue(const std::string& optionName, cons
     std::string typeName;
     if (i == 0) {
       // empty string
-    } else if (_charOptions.find(optionName) != _charOptions.end()) {
+    } else if (_charOptions.count(optionName)) {
       // do not check strings
-    } else if (_doubleOptions.find(optionName) != _doubleOptions.end()) {
+    } else if (_doubleOptions.count(optionName)) {
       // check if value is double
-      char * endPtr;
-      strtod(ptr, &endPtr);
-      typeOk = (ptr != endPtr);
+      ToDbl(ptr, &typeOk);
       typeName = "real";
+    } else if (_boolOptions.count(optionName)) {
+      // check if value is bool
+      ToBool(ptr, &typeOk);
+      typeName = "bool";
     } else {
       // check if value is int
-      char * endPtr;
-      strtol(ptr, &endPtr, 10);
-      typeOk = (ptr != endPtr);
+      ToInt(ptr, &typeOk);
       typeName = "integer";
     }
     if (!typeOk) {
       std::string msg = "Advanced option '" + optionName + "' = '" + optionValue + "' but must be " + typeName;
       throw std::invalid_argument(msg);
     }
-    op_val->second = optionValue;
+    std::string value( ptr, i );
+    if ( _defaultOptionValues[ optionName ] == value )
+      value.clear();
+
+    op_val->second = value;
+
     NotifySubMeshesHypothesisModification();
   }
 }
 
 //=============================================================================
 void BLSURFPlugin_Hypothesis::SetPreCADOptionValue(const std::string& optionName, const std::string& optionValue)
-    throw (std::invalid_argument) {
+{
   TOptionValues::iterator op_val = _preCADoption2value.find(optionName);
   if (op_val == _preCADoption2value.end()) {
-    std::string msg = "Unknown MG-CADSurf option: '" + optionName + "'";
-    throw std::invalid_argument(msg);
+    op_val = _option2value.find(optionName);
+    if (op_val == _option2value.end()) {
+      std::string msg = "Unknown MG-PreCAD option: '" + optionName + "'. Try SetAdvancedOption()";
+      throw std::invalid_argument(msg);
+    }
   }
-  if (op_val->second != optionValue) {
+  if (op_val->second != optionValue)
+  {
     const char* ptr = optionValue.c_str();
     // strip white spaces
     while (ptr[0] == ' ')
       ptr++;
-    int i = strlen(ptr);
+    size_t i = strlen(ptr);
     while (i != 0 && ptr[i - 1] == ' ')
       i--;
     // check value type
@@ -492,6 +1137,10 @@ void BLSURFPlugin_Hypothesis::SetPreCADOptionValue(const std::string& optionName
       strtod(ptr, &endPtr);
       typeOk = (ptr != endPtr);
       typeName = "real";
+    } else if (_boolOptions.count(optionName)) {
+      // check if value is bool
+      ToBool(ptr, &typeOk);
+      typeName = "bool";
     } else {
       // check if value is int
       char * endPtr;
@@ -503,35 +1152,79 @@ void BLSURFPlugin_Hypothesis::SetPreCADOptionValue(const std::string& optionName
       std::string msg = "PreCAD advanced option '" + optionName + "' = '" + optionValue + "' but must be " + typeName;
       throw std::invalid_argument(msg);
     }
-    op_val->second = optionValue;
+    std::string value( ptr, i );
+    if ( _defaultOptionValues[ optionName ] == value )
+      value.clear();
+
+    op_val->second = value;
+
     NotifySubMeshesHypothesisModification();
   }
 }
 
 //=============================================================================
-std::string BLSURFPlugin_Hypothesis::GetOptionValue(const std::string& optionName) throw (std::invalid_argument) {
-  TOptionValues::iterator op_val = _option2value.find(optionName);
-  if (op_val == _option2value.end()) {
-    std::string msg = "Unknown MG-CADSurf option: <";
-    msg += optionName + ">";
-    throw std::invalid_argument(msg);
+std::string BLSURFPlugin_Hypothesis::GetOptionValue(const std::string& optionName,
+                                                    bool*              isDefault) const
+{
+  TOptionValues::const_iterator op_val = _option2value.find(optionName);
+  if (op_val == _option2value.end())
+  {
+    op_val = _preCADoption2value.find(optionName);
+    if (op_val == _preCADoption2value.end())
+    {
+      op_val = _customOption2value.find(optionName);
+      if (op_val == _customOption2value.end())
+      {
+        std::string msg = "Unknown MG-CADSurf option: <" + optionName + ">";
+        throw std::invalid_argument(msg);
+      }
+    }
   }
-  return op_val->second;
+  std::string val = op_val->second;
+  if ( isDefault ) *isDefault = ( val.empty() );
+
+  if ( val.empty() && isDefault )
+  {
+    op_val = _defaultOptionValues.find( optionName );
+    if (op_val != _defaultOptionValues.end())
+      val = op_val->second;
+  }
+  return val;
 }
 
 //=============================================================================
-std::string BLSURFPlugin_Hypothesis::GetPreCADOptionValue(const std::string& optionName) throw (std::invalid_argument) {
-  TOptionValues::iterator op_val = _preCADoption2value.find(optionName);
-  if (op_val == _preCADoption2value.end()) {
-    std::string msg = "Unknown PRECAD option: <";
-    msg += optionName + ">";
-    throw std::invalid_argument(msg);
+std::string BLSURFPlugin_Hypothesis::GetPreCADOptionValue(const std::string& optionName,
+                                                          bool*              isDefault) const
+{
+  TOptionValues::const_iterator op_val = _preCADoption2value.find(optionName);
+  if (op_val == _preCADoption2value.end())
+  {
+    op_val = _option2value.find(optionName);
+    if (op_val == _option2value.end())
+    {
+      op_val = _customOption2value.find(optionName);
+      if (op_val == _customOption2value.end())
+      {
+        std::string msg = "Unknown MG-CADSurf option: <" + optionName + ">";
+        throw std::invalid_argument(msg);
+      }
+    }
+  }
+  std::string val = op_val->second;
+  if ( isDefault ) *isDefault = ( val.empty() );
+
+  if ( val.empty() && isDefault )
+  {
+    op_val = _defaultOptionValues.find( optionName );
+    if (op_val != _option2value.end())
+      val = op_val->second;
   }
-  return op_val->second;
+  return val;
 }
 
 //=============================================================================
-void BLSURFPlugin_Hypothesis::ClearOption(const std::string& optionName) {
+void BLSURFPlugin_Hypothesis::ClearOption(const std::string& optionName)
+{
   TOptionValues::iterator op_val = _customOption2value.find(optionName);
   if (op_val != _customOption2value.end())
    _customOption2value.erase(op_val);
@@ -539,61 +1232,73 @@ void BLSURFPlugin_Hypothesis::ClearOption(const std::string& optionName) {
     op_val = _option2value.find(optionName);
     if (op_val != _option2value.end())
       op_val->second.clear();
+    else {
+      op_val = _preCADoption2value.find(optionName);
+      if (op_val != _preCADoption2value.end())
+        op_val->second.clear();
+    }
   }
 }
 
 //=============================================================================
-void BLSURFPlugin_Hypothesis::ClearPreCADOption(const std::string& optionName) {
-  TOptionValues::iterator op_val = _customPreCADOption2value.find(optionName);
-  if (op_val != _customPreCADOption2value.end())
-    _customPreCADOption2value.erase(op_val);
-  else {
-    op_val = _preCADoption2value.find(optionName);
-    if (op_val != _preCADoption2value.end())
-      op_val->second.clear();
-  }
+void BLSURFPlugin_Hypothesis::ClearPreCADOption(const std::string& optionName)
+{
+  TOptionValues::iterator op_val = _preCADoption2value.find(optionName);
+  if (op_val != _preCADoption2value.end())
+    op_val->second.clear();
 }
 
 //=============================================================================
 void BLSURFPlugin_Hypothesis::AddOption(const std::string& optionName, const std::string& optionValue)
 {
+  bool modif = true;
   TOptionValues::iterator op_val = _option2value.find(optionName);
-  if (op_val != _option2value.end()) {
+  if (op_val != _option2value.end())
+  {
     if (op_val->second != optionValue)
       op_val->second = optionValue;
+    else
+      modif = false;
   }
-  else {
-    op_val = _customOption2value.find(optionName);
-    if (op_val == _customOption2value.end())
-      _customOption2value[optionName] = optionValue;
-    else if (op_val->second != optionValue)
-      op_val->second = optionValue;
+  else
+  {
+    op_val = _preCADoption2value.find(optionName);
+    if (op_val != _preCADoption2value.end())
+    {
+      if (op_val->second != optionValue)
+        op_val->second = optionValue;
+      else
+        modif = false;
+    }
+    else if ( optionValue.empty() )
+    {
+      _customOption2value.erase( optionName );
+    }
+    else
+    {
+      op_val = _customOption2value.find(optionName);
+      if (op_val == _customOption2value.end())
+        _customOption2value[optionName] = optionValue;
+      else if (op_val->second != optionValue)
+        op_val->second = optionValue;
+      else
+        modif = false;
+    }
   }
-  NotifySubMeshesHypothesisModification();
+  if ( modif )
+    NotifySubMeshesHypothesisModification();
 }
 
 //=============================================================================
 void BLSURFPlugin_Hypothesis::AddPreCADOption(const std::string& optionName, const std::string& optionValue)
 {
-  TOptionValues::iterator op_val = _preCADoption2value.find(optionName);
-  if (op_val != _preCADoption2value.end()) {
-    if (op_val->second != optionValue)
-      op_val->second = optionValue;
-  }
-  else {
-    op_val = _customPreCADOption2value.find(optionName);
-    if (op_val == _customPreCADOption2value.end())
-      _customPreCADOption2value[optionName] = optionValue;
-    else if (op_val->second != optionValue)
-      op_val->second = optionValue;
-  }
-  NotifySubMeshesHypothesisModification();
+  AddOption( optionName, optionValue );
 }
 
 //=============================================================================
-std::string BLSURFPlugin_Hypothesis::GetOption(const std::string& optionName)
+std::string BLSURFPlugin_Hypothesis::GetOption(const std::string& optionName) const
 {
-  TOptionValues::iterator op_val = _customOption2value.find(optionName);
+  TOptionValues::const_iterator op_val = _customOption2value.find(optionName);
   if (op_val != _customOption2value.end())
     return op_val->second;
   else
@@ -601,15 +1306,37 @@ std::string BLSURFPlugin_Hypothesis::GetOption(const std::string& optionName)
 }
 
 //=============================================================================
-std::string BLSURFPlugin_Hypothesis::GetPreCADOption(const std::string& optionName)
+std::string BLSURFPlugin_Hypothesis::GetPreCADOption(const std::string& optionName) const
 {
-  TOptionValues::iterator op_val = _customPreCADOption2value.find(optionName);
-  if (op_val != _customPreCADOption2value.end())
+  TOptionValues::const_iterator op_val = _customOption2value.find(optionName);
+  if (op_val != _customOption2value.end())
     return op_val->second;
   else
     return "";
 }
 
+//=============================================================================
+BLSURFPlugin_Hypothesis::TOptionValues BLSURFPlugin_Hypothesis::GetOptionValues() const
+{
+  TOptionValues vals;
+  TOptionValues::const_iterator op_val = _option2value.begin();
+  for ( ; op_val != _option2value.end(); ++op_val )
+    vals.insert( make_pair( op_val->first, GetOptionValue( op_val->first, GET_DEFAULT() )));
+
+  return vals;
+}
+
+//=============================================================================
+BLSURFPlugin_Hypothesis::TOptionValues BLSURFPlugin_Hypothesis::GetPreCADOptionValues() const
+{
+  TOptionValues vals;
+  TOptionValues::const_iterator op_val = _preCADoption2value.begin();
+  for ( ; op_val != _preCADoption2value.end(); ++op_val )
+    vals.insert( make_pair( op_val->first, GetPreCADOptionValue( op_val->first, GET_DEFAULT() )));
+
+  return vals;
+}
+
 //=======================================================================
 //function : SetSizeMapEntry
 //=======================================================================
@@ -778,7 +1505,6 @@ void BLSURFPlugin_Hypothesis::ClearEntry(const std::string& entry,
            ++it_clAt;
        }
        while ( it_clAt != _classAttractors.end() );
-       MESSAGE("_classAttractors.size() = "<<_classAttractors.size())
        NotifySubMeshesHypothesisModification();
      }
      else
@@ -805,7 +1531,6 @@ void BLSURFPlugin_Hypothesis::ClearSizeMaps() {
 //                                                        bool toEnforceInternalVertices,
 //                                                        TEnfGroupName theGroupName) {
 
-//  MESSAGE("BLSURFPlugin_Hypothesis::SetInternalEnforcedVertex("<< theFaceEntry << ", "
 //      << toEnforceInternalVertices << ", " << theGroupName << ")");
   
 //  TFaceEntryInternalVerticesList::iterator it = _faceEntryInternalVerticesList.find(theFaceEntry);
@@ -828,15 +1553,14 @@ void BLSURFPlugin_Hypothesis::ClearSizeMaps() {
 //=======================================================================
 //function : SetEnforcedVertex
 //=======================================================================
-bool BLSURFPlugin_Hypothesis::SetEnforcedVertex(TEntry theFaceEntry, TEnfName theVertexName, TEntry theVertexEntry,
-                                                TEnfGroupName theGroupName, double x, double y, double z) {
-
-  MESSAGE("BLSURFPlugin_Hypothesis::SetEnforcedVertex("<< theFaceEntry << ", "
-      << x << ", " << y << ", " << z << ", " << theVertexName << ", " << theVertexEntry << ", " << theGroupName << ")");
-
+bool BLSURFPlugin_Hypothesis::SetEnforcedVertex(TEntry        theFaceEntry,
+                                                TEnfName      theVertexName,
+                                                TEntry        theVertexEntry,
+                                                TEnfGroupName theGroupName,
+                                                double x, double y, double z)
+{
   SetPhysicalMesh(PhysicalLocalSize);
 
-  //  TEnfVertexList::iterator it;
   bool toNotify = false;
   bool toCreate = true;
 
@@ -853,27 +1577,23 @@ bool BLSURFPlugin_Hypothesis::SetEnforcedVertex(TEntry theFaceEntry, TEnfName th
   newEnfVertex->grpName = theGroupName;
   newEnfVertex->faceEntries.clear();
   newEnfVertex->faceEntries.insert(theFaceEntry);
-  
-  
+
+
   // update _enfVertexList
   TEnfVertexList::iterator it = _enfVertexList.find(newEnfVertex);
   if (it != _enfVertexList.end()) {
     toCreate = false;
     oldEnVertex = (*it);
-    MESSAGE("Enforced Vertex was found => Update");
     if (oldEnVertex->name != theVertexName) {
-      MESSAGE("Update name from \"" << oldEnVertex->name << "\" to \"" << theVertexName << "\"");
       oldEnVertex->name = theVertexName;
       toNotify = true;
     }
     if (oldEnVertex->grpName != theGroupName) {
-      MESSAGE("Update group name from \"" << oldEnVertex->grpName << "\" to \"" << theGroupName << "\"");
       oldEnVertex->grpName = theGroupName;
       toNotify = true;
     }
     TEntryList::iterator it_faceEntries = oldEnVertex->faceEntries.find(theFaceEntry);
     if (it_faceEntries == oldEnVertex->faceEntries.end()) {
-      MESSAGE("Update face list by adding \"" << theFaceEntry << "\"");
       oldEnVertex->faceEntries.insert(theFaceEntry);
       _faceEntryEnfVertexListMap[theFaceEntry].insert(oldEnVertex);
       toNotify = true;
@@ -896,34 +1616,46 @@ bool BLSURFPlugin_Hypothesis::SetEnforcedVertex(TEntry theFaceEntry, TEnfName th
 //   //////// CREATE ////////////
   if (toCreate) {
     toNotify = true;
-    MESSAGE("Creating new enforced vertex");
-    _faceEntryEnfVertexListMap[theFaceEntry].insert(newEnfVertex);
-    _enfVertexList.insert(newEnfVertex);
-    if (theVertexEntry == "") {
-      _faceEntryCoordsListMap[theFaceEntry].insert(newEnfVertex->coords);
-      _coordsEnfVertexMap[newEnfVertex->coords] = newEnfVertex;
-    }
-    else {
-      _faceEntryEnfVertexEntryListMap[theFaceEntry].insert(newEnfVertex->geomEntry);
-      _enfVertexEntryEnfVertexMap[newEnfVertex->geomEntry] = newEnfVertex;
-    }
+    AddEnforcedVertex( theFaceEntry, newEnfVertex );
+  }
+  else {
+    delete newEnfVertex;
   }
 
   if (toNotify)
     NotifySubMeshesHypothesisModification();
 
-  MESSAGE("BLSURFPlugin_Hypothesis::SetEnforcedVertex END");
   return toNotify;
 }
 
+//=======================================================================
+//function : AddEnforcedVertex
+//=======================================================================
+
+void BLSURFPlugin_Hypothesis::AddEnforcedVertex( const TEntry& faceEntry,
+                                                 TEnfVertex *  newEnfVertex )
+{
+  if ( newEnfVertex )
+  {
+    _faceEntryEnfVertexListMap[faceEntry].insert(newEnfVertex);
+    _enfVertexList.insert(newEnfVertex);
+    if ( newEnfVertex->geomEntry.empty() ) {
+      _faceEntryCoordsListMap[faceEntry].insert(newEnfVertex->coords);
+      _coordsEnfVertexMap[newEnfVertex->coords] = newEnfVertex;
+    }
+    else {
+      _faceEntryEnfVertexEntryListMap[faceEntry].insert(newEnfVertex->geomEntry);
+      _enfVertexEntryEnfVertexMap[newEnfVertex->geomEntry] = newEnfVertex;
+    }
+  }
+}
 
 //=======================================================================
 //function : GetEnforcedVertices
 //=======================================================================
 
 BLSURFPlugin_Hypothesis::TEnfVertexList BLSURFPlugin_Hypothesis::GetEnfVertexList(const TEntry& theFaceEntry)
-    throw (std::invalid_argument) {
-
+{
   if (_faceEntryEnfVertexListMap.count(theFaceEntry) > 0)
     return _faceEntryEnfVertexListMap[theFaceEntry];
   else
@@ -938,9 +1670,8 @@ BLSURFPlugin_Hypothesis::TEnfVertexList BLSURFPlugin_Hypothesis::GetEnfVertexLis
 //function : GetEnfVertexCoordsList
 //=======================================================================
 
-BLSURFPlugin_Hypothesis::TEnfVertexCoordsList BLSURFPlugin_Hypothesis::GetEnfVertexCoordsList(
-    const TEntry& theFaceEntry) throw (std::invalid_argument) {
-
+BLSURFPlugin_Hypothesis::TEnfVertexCoordsList BLSURFPlugin_Hypothesis::GetEnfVertexCoordsList(const TEntry& theFaceEntry)
+{
   if (_faceEntryCoordsListMap.count(theFaceEntry) > 0)
     return _faceEntryCoordsListMap[theFaceEntry];
 
@@ -954,8 +1685,7 @@ BLSURFPlugin_Hypothesis::TEnfVertexCoordsList BLSURFPlugin_Hypothesis::GetEnfVer
 //=======================================================================
 
 BLSURFPlugin_Hypothesis::TEntryList BLSURFPlugin_Hypothesis::GetEnfVertexEntryList(const TEntry& theFaceEntry)
-    throw (std::invalid_argument) {
-
+{
   if (_faceEntryEnfVertexEntryListMap.count(theFaceEntry) > 0)
     return _faceEntryEnfVertexEntryListMap[theFaceEntry];
 
@@ -969,8 +1699,7 @@ BLSURFPlugin_Hypothesis::TEntryList BLSURFPlugin_Hypothesis::GetEnfVertexEntryLi
 //=======================================================================
 
 BLSURFPlugin_Hypothesis::TEnfVertex* BLSURFPlugin_Hypothesis::GetEnfVertex(TEnfVertexCoords coords)
-    throw (std::invalid_argument) {
-
+{
   if (_coordsEnfVertexMap.count(coords) > 0)
     return _coordsEnfVertexMap[coords];
 
@@ -984,8 +1713,7 @@ BLSURFPlugin_Hypothesis::TEnfVertex* BLSURFPlugin_Hypothesis::GetEnfVertex(TEnfV
 //=======================================================================
 
 BLSURFPlugin_Hypothesis::TEnfVertex* BLSURFPlugin_Hypothesis::GetEnfVertex(const TEntry& theEnfVertexEntry)
-    throw (std::invalid_argument) {
-
+{
   if (_enfVertexEntryEnfVertexMap.count(theEnfVertexEntry) > 0)
     return _enfVertexEntryEnfVertexMap[theEnfVertexEntry];
 
@@ -1010,9 +1738,10 @@ BLSURFPlugin_Hypothesis::TEnfVertex* BLSURFPlugin_Hypothesis::GetEnfVertex(const
 //function : ClearEnforcedVertex
 //=======================================================================
 
-bool BLSURFPlugin_Hypothesis::ClearEnforcedVertex(const TEntry& theFaceEntry, double x, double y, double z,
-    const TEntry& theVertexEntry) throw (std::invalid_argument) {
-
+bool BLSURFPlugin_Hypothesis::ClearEnforcedVertex(const TEntry& theFaceEntry,
+                                                  double x, double y, double z,
+                                                  const TEntry& theVertexEntry)
+{
   bool toNotify = false;
   std::ostringstream msg;
   TEnfVertex *oldEnfVertex;
@@ -1026,7 +1755,6 @@ bool BLSURFPlugin_Hypothesis::ClearEnforcedVertex(const TEntry& theFaceEntry, do
   TEnfVertexEntryEnfVertexMap::iterator it_enfVertexEntry = _enfVertexEntryEnfVertexMap.find(theVertexEntry);
   if (it_enfVertexEntry != _enfVertexEntryEnfVertexMap.end()) {
     // Success
-    MESSAGE("Found enforced vertex with geom entry " << theVertexEntry);
     oldEnfVertex = it_enfVertexEntry->second;
 
     _enfVertexEntryEnfVertexMap.erase(it_enfVertexEntry);
@@ -1048,7 +1776,6 @@ bool BLSURFPlugin_Hypothesis::ClearEnforcedVertex(const TEntry& theFaceEntry, do
     TCoordsEnfVertexMap::iterator it_coords_enf = _coordsEnfVertexMap.find(coords);
     if (it_coords_enf != _coordsEnfVertexMap.end()) {
       // Success
-      MESSAGE("Found enforced vertex with coords " << x << ", " << y << ", " << z);
       oldEnfVertex = it_coords_enf->second;
 
       _coordsEnfVertexMap.erase(it_coords_enf);
@@ -1071,8 +1798,6 @@ bool BLSURFPlugin_Hypothesis::ClearEnforcedVertex(const TEntry& theFaceEntry, do
     }
   }
 
-  MESSAGE("Remove enf vertex from _enfVertexList");
-
   // update _enfVertexList
   TEnfVertexList::iterator it = _enfVertexList.find(oldEnfVertex);
   if (it != _enfVertexList.end()) {
@@ -1081,7 +1806,6 @@ bool BLSURFPlugin_Hypothesis::ClearEnforcedVertex(const TEntry& theFaceEntry, do
       _enfVertexList.erase(it);
       toNotify = true;
     }
-    MESSAGE("Done");
   }
 
   // update _faceEntryEnfVertexListMap
@@ -1089,9 +1813,7 @@ bool BLSURFPlugin_Hypothesis::ClearEnforcedVertex(const TEntry& theFaceEntry, do
   currentEnfVertexList.erase(oldEnfVertex);
 
   if (currentEnfVertexList.size() == 0) {
-    MESSAGE("Remove _faceEntryEnfVertexListMap[" << theFaceEntry <<"]");
     _faceEntryEnfVertexListMap.erase(theFaceEntry);
-    MESSAGE("Done");
   }
 
   if (toNotify)
@@ -1104,8 +1826,8 @@ bool BLSURFPlugin_Hypothesis::ClearEnforcedVertex(const TEntry& theFaceEntry, do
 //function : ClearEnforcedVertices
 //=======================================================================
 
-bool BLSURFPlugin_Hypothesis::ClearEnforcedVertices(const TEntry& theFaceEntry) throw (std::invalid_argument) {
-
+bool BLSURFPlugin_Hypothesis::ClearEnforcedVertices(const TEntry& theFaceEntry)
+{
   bool toNotify = false;
   TEnfVertex *oldEnfVertex;
 
@@ -1126,7 +1848,6 @@ bool BLSURFPlugin_Hypothesis::ClearEnforcedVertices(const TEntry& theFaceEntry)
           _enfVertexList.erase(it);
           toNotify = true;
         }
-        MESSAGE("Done");
       }
     }
     _faceEntryCoordsListMap.erase(it_entry_coords);
@@ -1150,7 +1871,6 @@ bool BLSURFPlugin_Hypothesis::ClearEnforcedVertices(const TEntry& theFaceEntry)
           _enfVertexList.erase(it);
           toNotify = true;
         }
-        MESSAGE("Done");
       }
     }
     _faceEntryEnfVertexEntryListMap.erase(it_entry_entry);
@@ -1169,18 +1889,25 @@ bool BLSURFPlugin_Hypothesis::ClearEnforcedVertices(const TEntry& theFaceEntry)
 //=======================================================================
 //function : ClearAllEnforcedVertices
 //=======================================================================
-void BLSURFPlugin_Hypothesis::ClearAllEnforcedVertices() {
+void BLSURFPlugin_Hypothesis::ClearAllEnforcedVertices()
+{
   _faceEntryEnfVertexListMap.clear();
-  _enfVertexList.clear();
   _faceEntryCoordsListMap.clear();
   _coordsEnfVertexMap.clear();
   _faceEntryEnfVertexEntryListMap.clear();
   _enfVertexEntryEnfVertexMap.clear();
+  
+  TEnfVertexList::iterator it_enfVertex = _enfVertexList.begin();
+  for ( ; it_enfVertex != _enfVertexList.end(); ++it_enfVertex )
+    delete *it_enfVertex;
+  _enfVertexList.clear();
+
 //  Enable internal enforced vertices on specific face if requested by user
 //  _faceEntryInternalVerticesList.clear();
   NotifySubMeshesHypothesisModification();
 }
 
+
 //================================================================================
 /*!
  * \brief Return the enforced vertices
@@ -1189,7 +1916,8 @@ void BLSURFPlugin_Hypothesis::ClearAllEnforcedVertices() {
 
 
 BLSURFPlugin_Hypothesis::TFaceEntryEnfVertexListMap BLSURFPlugin_Hypothesis::GetAllEnforcedVerticesByFace(
-    const BLSURFPlugin_Hypothesis* hyp) {
+    const BLSURFPlugin_Hypothesis* hyp)
+{
   return hyp ? hyp->_GetAllEnforcedVerticesByFace() : GetDefaultFaceEntryEnfVertexListMap();
 }
 
@@ -1210,31 +1938,36 @@ BLSURFPlugin_Hypothesis::TEnfGroupName BLSURFPlugin_Hypothesis::GetInternalEnfor
 }
 
 BLSURFPlugin_Hypothesis::TEnfVertexList BLSURFPlugin_Hypothesis::GetAllEnforcedVertices(
-    const BLSURFPlugin_Hypothesis* hyp) {
+    const BLSURFPlugin_Hypothesis* hyp)
+{
   return hyp ? hyp->_GetAllEnforcedVertices() : GetDefaultEnfVertexList();
 }
 
 BLSURFPlugin_Hypothesis::TFaceEntryCoordsListMap BLSURFPlugin_Hypothesis::GetAllCoordsByFace(
-    const BLSURFPlugin_Hypothesis* hyp) {
+    const BLSURFPlugin_Hypothesis* hyp)
+{
   return hyp ? hyp->_GetAllCoordsByFace() : GetDefaultFaceEntryCoordsListMap();
 }
 
 BLSURFPlugin_Hypothesis::TCoordsEnfVertexMap BLSURFPlugin_Hypothesis::GetAllEnforcedVerticesByCoords(
-    const BLSURFPlugin_Hypothesis* hyp) {
+    const BLSURFPlugin_Hypothesis* hyp)
+{
   return hyp ? hyp->_GetAllEnforcedVerticesByCoords() : GetDefaultCoordsEnfVertexMap();
 }
 
 BLSURFPlugin_Hypothesis::TFaceEntryEnfVertexEntryListMap BLSURFPlugin_Hypothesis::GetAllEnfVertexEntriesByFace(
-    const BLSURFPlugin_Hypothesis* hyp) {
+    const BLSURFPlugin_Hypothesis* hyp)
+{
   return hyp ? hyp->_GetAllEnfVertexEntriesByFace() : GetDefaultFaceEntryEnfVertexEntryListMap();
 }
 
 BLSURFPlugin_Hypothesis::TEnfVertexEntryEnfVertexMap BLSURFPlugin_Hypothesis::GetAllEnforcedVerticesByEnfVertexEntry(
-    const BLSURFPlugin_Hypothesis* hyp) {
+    const BLSURFPlugin_Hypothesis* hyp)
+{
   return hyp ? hyp->_GetAllEnforcedVerticesByEnfVertexEntry() : GetDefaultEnfVertexEntryEnfVertexMap();
 }
 
-std::set<int> BLSURFPlugin_Hypothesis::GetEnfVertexNodeIDs(TEnfGroupName theGroupName) throw (std::invalid_argument)
+std::set<smIdType> BLSURFPlugin_Hypothesis::GetEnfVertexNodeIDs(TEnfGroupName theGroupName)
 {
   TGroupNameNodeIDMap::const_iterator it = _groupNameNodeIDMap.find(theGroupName);
   if (it != _groupNameNodeIDMap.end()) {
@@ -1245,16 +1978,16 @@ std::set<int> BLSURFPlugin_Hypothesis::GetEnfVertexNodeIDs(TEnfGroupName theGrou
   throw std::invalid_argument(msg.str());
 }
 
-void BLSURFPlugin_Hypothesis::AddEnfVertexNodeID(TEnfGroupName theGroupName,int theNodeID)
+void BLSURFPlugin_Hypothesis::AddEnfVertexNodeID(TEnfGroupName theGroupName,smIdType theNodeID)
 {
   _groupNameNodeIDMap[theGroupName].insert(theNodeID);
 }
 
-void BLSURFPlugin_Hypothesis::RemoveEnfVertexNodeID(TEnfGroupName theGroupName,int theNodeID) throw (std::invalid_argument)
+void BLSURFPlugin_Hypothesis::RemoveEnfVertexNodeID(TEnfGroupName theGroupName,smIdType theNodeID)
 {
   TGroupNameNodeIDMap::iterator it = _groupNameNodeIDMap.find(theGroupName);
   if (it != _groupNameNodeIDMap.end()) {
-    std::set<int>::iterator IDit = it->second.find(theNodeID);
+    std::set<smIdType>::iterator IDit = it->second.find(theNodeID);
     if (IDit != it->second.end())
       it->second.erase(IDit);
     std::ostringstream msg;
@@ -1268,7 +2001,8 @@ void BLSURFPlugin_Hypothesis::RemoveEnfVertexNodeID(TEnfGroupName theGroupName,i
 
 
 //=============================================================================
-void BLSURFPlugin_Hypothesis::SetInternalEnforcedVertexAllFaces(bool toEnforceInternalVertices) {
+void BLSURFPlugin_Hypothesis::SetInternalEnforcedVertexAllFaces(bool toEnforceInternalVertices)
+{
   if (toEnforceInternalVertices != _enforcedInternalVerticesAllFaces) {
     _enforcedInternalVerticesAllFaces = toEnforceInternalVertices;
     if (toEnforceInternalVertices)
@@ -1279,7 +2013,8 @@ void BLSURFPlugin_Hypothesis::SetInternalEnforcedVertexAllFaces(bool toEnforceIn
 
 
 //=============================================================================
-void BLSURFPlugin_Hypothesis::SetInternalEnforcedVertexAllFacesGroup(BLSURFPlugin_Hypothesis::TEnfGroupName theGroupName) {
+void BLSURFPlugin_Hypothesis::SetInternalEnforcedVertexAllFacesGroup(BLSURFPlugin_Hypothesis::TEnfGroupName theGroupName)
+{
   if (std::string(theGroupName) != std::string(_enforcedInternalVerticesAllFacesGroup)) {
     _enforcedInternalVerticesAllFacesGroup = theGroupName;
     NotifySubMeshesHypothesisModification();
@@ -1288,38 +2023,44 @@ void BLSURFPlugin_Hypothesis::SetInternalEnforcedVertexAllFacesGroup(BLSURFPlugi
 
 //=============================================================================
 BLSURFPlugin_Hypothesis::TPreCadPeriodicityVector BLSURFPlugin_Hypothesis::GetPreCadFacesPeriodicityVector(
-    const BLSURFPlugin_Hypothesis* hyp) {
+    const BLSURFPlugin_Hypothesis* hyp)
+{
   return hyp ? hyp->_GetPreCadFacesPeriodicityVector() : GetDefaultPreCadFacesPeriodicityVector();
 }
 
 //=============================================================================
 BLSURFPlugin_Hypothesis::TPreCadPeriodicityVector BLSURFPlugin_Hypothesis::GetPreCadEdgesPeriodicityVector(
-    const BLSURFPlugin_Hypothesis* hyp) {
+    const BLSURFPlugin_Hypothesis* hyp)
+{
   return hyp ? hyp->_GetPreCadEdgesPeriodicityVector() : GetDefaultPreCadEdgesPeriodicityVector();
 }
 
 //=============================================================================
 BLSURFPlugin_Hypothesis::TFacesPeriodicityVector BLSURFPlugin_Hypothesis::GetFacesPeriodicityVector(
-    const BLSURFPlugin_Hypothesis* hyp) {
+    const BLSURFPlugin_Hypothesis* hyp)
+{
   return hyp ? hyp->_GetFacesPeriodicityVector() : GetDefaultFacesPeriodicityVector();
 }
 
 //=============================================================================
 BLSURFPlugin_Hypothesis::TEdgesPeriodicityVector BLSURFPlugin_Hypothesis::GetEdgesPeriodicityVector(
-    const BLSURFPlugin_Hypothesis* hyp){
+    const BLSURFPlugin_Hypothesis* hyp)
+{
   return hyp ? hyp->_GetEdgesPeriodicityVector() : GetDefaultEdgesPeriodicityVector();
 }
 
 //=============================================================================
 BLSURFPlugin_Hypothesis::TVerticesPeriodicityVector BLSURFPlugin_Hypothesis::GetVerticesPeriodicityVector(
-    const BLSURFPlugin_Hypothesis* hyp){
+    const BLSURFPlugin_Hypothesis* hyp)
+{
   return hyp ? hyp->_GetVerticesPeriodicityVector() : GetDefaultVerticesPeriodicityVector();
 }
 
 //=======================================================================
 //function : ClearAllEnforcedVertices
 //=======================================================================
-void BLSURFPlugin_Hypothesis::ClearPreCadPeriodicityVectors() {
+void BLSURFPlugin_Hypothesis::ClearPreCadPeriodicityVectors()
+{
   _preCadFacesPeriodicityVector.clear();
   _preCadEdgesPeriodicityVector.clear();
   NotifySubMeshesHypothesisModification();
@@ -1329,7 +2070,8 @@ void BLSURFPlugin_Hypothesis::ClearPreCadPeriodicityVectors() {
 //function : AddPreCadFacesPeriodicity
 //=======================================================================
 void BLSURFPlugin_Hypothesis::AddPreCadFacesPeriodicity(TEntry theFace1Entry, TEntry theFace2Entry,
-    std::vector<std::string> &theSourceVerticesEntries, std::vector<std::string> &theTargetVerticesEntries) {
+                                                        std::vector<std::string> &theSourceVerticesEntries, std::vector<std::string> &theTargetVerticesEntries)
+{
 
   TPreCadPeriodicity preCadFacesPeriodicity;
   preCadFacesPeriodicity.shape1Entry = theFace1Entry;
@@ -1346,8 +2088,8 @@ void BLSURFPlugin_Hypothesis::AddPreCadFacesPeriodicity(TEntry theFace1Entry, TE
 //function : AddPreCadEdgesPeriodicity
 //=======================================================================
 void BLSURFPlugin_Hypothesis::AddPreCadEdgesPeriodicity(TEntry theEdge1Entry, TEntry theEdge2Entry,
-    std::vector<std::string> &theSourceVerticesEntries, std::vector<std::string> &theTargetVerticesEntries) {
-
+    std::vector<std::string> &theSourceVerticesEntries, std::vector<std::string> &theTargetVerticesEntries)
+{
   TPreCadPeriodicity preCadEdgesPeriodicity;
   preCadEdgesPeriodicity.shape1Entry = theEdge1Entry;
   preCadEdgesPeriodicity.shape2Entry = theEdge2Entry;
@@ -1359,97 +2101,49 @@ void BLSURFPlugin_Hypothesis::AddPreCadEdgesPeriodicity(TEntry theEdge1Entry, TE
   NotifySubMeshesHypothesisModification();
 }
 
-//=======================================================================
-//function : AddFacePeriodicity
-//=======================================================================
-void BLSURFPlugin_Hypothesis::AddFacePeriodicity(TEntry theFace1Entry, TEntry theFace2Entry) {
-
-  std::pair< TEntry, TEntry > pairOfFacesEntries = std::make_pair(theFace1Entry, theFace2Entry);
-
-  _facesPeriodicityVector.push_back(pairOfFacesEntries);
-
-  // Removed for performance reason since AddFacePeriodicity is called multiple times (one time for each face)
-  // Does not affect the behaviour since it is only called via python, not via GUI.
-  //NotifySubMeshesHypothesisModification();
-}
-
-
-//=======================================================================
-//function : AddEdgePeriodicity
-//=======================================================================
-void BLSURFPlugin_Hypothesis::AddEdgePeriodicity(TEntry theFace1Entry, TEntry theEdge1Entry, TEntry theFace2Entry, TEntry theEdge2Entry, int edge_orientation) {
-
-  TEdgePeriodicity edgePeriodicity;
-  edgePeriodicity.theFace1Entry = theFace1Entry;
-  edgePeriodicity.theEdge1Entry = theEdge1Entry;
-  edgePeriodicity.theFace2Entry = theFace2Entry;
-  edgePeriodicity.theEdge2Entry = theEdge2Entry;
-  edgePeriodicity.edge_orientation = edge_orientation;
-
-  _edgesPeriodicityVector.push_back(edgePeriodicity);
-
-  // Removed for performance reason since AddEdgePeriodicity is called multiple times (one time for each edge)
-  // Does not affect the behaviour since it is only called via python, not via GUI.
-  //NotifySubMeshesHypothesisModification();
-}
-
-//=======================================================================
-//function : AddVertexPeriodicity
-//=======================================================================
-void BLSURFPlugin_Hypothesis::AddVertexPeriodicity(TEntry theEdge1Entry, TEntry theVertex1Entry, TEntry theEdge2Entry, TEntry theVertex2Entry) {
-
-  TVertexPeriodicity vertexPeriodicity;
-  vertexPeriodicity.theEdge1Entry = theEdge1Entry;
-  vertexPeriodicity.theVertex1Entry = theVertex1Entry;
-  vertexPeriodicity.theEdge2Entry = theEdge2Entry;
-  vertexPeriodicity.theVertex2Entry = theVertex2Entry;
-
-  _verticesPeriodicityVector.push_back(vertexPeriodicity);
-
-  // Removed for performance reason since AddVertexPeriodicity is called multiple times (one time for each vertex)
-  // Does not affect the behaviour since it is only called via python, not via GUI.
-  //NotifySubMeshesHypothesisModification();
-}
-
 //=============================================================================
-std::ostream & BLSURFPlugin_Hypothesis::SaveTo(std::ostream & save) {
-   // We must keep at least the same number of arguments when increasing the SALOME version
-   // When MG-CADSurf becomes CADMESH, some parameters were fused into a single one. Thus the same
-   // parameter can be written several times to keep the old global number of parameters.
+std::ostream & BLSURFPlugin_Hypothesis::SaveTo(std::ostream & save)
+{
+  // We must keep at least the same number of arguments when increasing the SALOME version
+  // When MG-CADSurf becomes CADMESH, some parameters were fused into a single one. Thus the same
+  // parameter can be written several times to keep the old global number of parameters.
+
+  // Treat old options which are now in the advanced options
+  TOptionValues::iterator op_val;
+  int _decimesh = -1;
+  int _preCADRemoveNanoEdges = -1;
+  double _preCADEpsNano = -1.0;
+  op_val = _option2value.find("respect_geometry");
+  if (op_val != _option2value.end()) {
+    std::string value = op_val->second;
+    if (!value.empty())
+      _decimesh = value.compare("1") == 0 ? 1 : 0;
+  }
+  op_val = _preCADoption2value.find("remove_tiny_edges");
+  if (op_val != _preCADoption2value.end()) {
+    std::string value = op_val->second;
+    if (!value.empty())
+      _preCADRemoveNanoEdges = value.compare("1") == 0 ? 1 : 0;
+  }
+  op_val = _preCADoption2value.find("tiny_edge_length");
+  if (op_val != _preCADoption2value.end()) {
+    std::string value = op_val->second;
+    if (!value.empty())
+      _preCADEpsNano = strtod(value.c_str(), NULL);
+  }
 
-   // Treat old options which are now in the advanced options
-   TOptionValues::iterator op_val;
-   int _decimesh = -1;
-   int _preCADRemoveNanoEdges = -1;
-   double _preCADEpsNano = -1.0;
-   op_val = _option2value.find("respect_geometry");
-   if (op_val != _option2value.end()) {
-     std::string value = op_val->second;
-     if (!value.empty())
-       _decimesh = value.compare("1") == 0 ? 1 : 0;
-   }
-   op_val = _preCADoption2value.find("remove_tiny_edges");
-   if (op_val != _preCADoption2value.end()) {
-     std::string value = op_val->second;
-     if (!value.empty())
-       _preCADRemoveNanoEdges = value.compare("1") == 0 ? 1 : 0;
-   }
-   op_val = _preCADoption2value.find("tiny_edge_length");
-   if (op_val != _preCADoption2value.end()) {
-     std::string value = op_val->second;
-     if (!value.empty())
-       _preCADEpsNano = strtod(value.c_str(), NULL);
-   }
-   
   save << " " << (int) _topology << " " << (int) _physicalMesh << " " << (int) _geometricMesh << " " << _phySize << " "
-      << _angleMesh << " " << _gradation << " " << (int) _quadAllowed << " " << _decimesh;
+       << _angleMesh << " " << _gradation << " " << (int) _elementType << " " << _decimesh;
   save << " " << _minSize << " " << _maxSize << " " << _angleMesh << " " << _minSize << " " << _maxSize << " " << _verb;
   save << " " << (int) _preCADMergeEdges << " " << _preCADRemoveNanoEdges << " " << (int) _preCADDiscardInput << " " << _preCADEpsNano ;
   save << " " << (int) _enforcedInternalVerticesAllFaces;
   save << " " << (int) _phySizeRel << " " << (int) _minSizeRel << " " << (int) _maxSizeRel << " " << _chordalError ;
   save << " " << (int) _anisotropic << " " << _anisotropicRatio << " " << (int) _removeTinyEdges << " " << _tinyEdgeLength ;
   save << " " << (int) _badElementRemoval << " " << _badElementAspectRatio << " " << (int) _optimizeMesh << " " << (int) _quadraticMesh ;
-  save << " " << (int) _preCADProcess3DTopology;
+  save << " " << (int) _preCADProcess3DTopology << " " << (int) _preCADRemoveDuplicateCADFaces;
+  save << " " << (int)_optimiseTinyEdges << " " << _tinyEdgeOptimisationLength;
+  save << " " << (int)_correctSurfaceIntersec << " " << _corrSurfaceIntersCost;
+  save << " " << (int)_useGradation << " " << (int)_useVolumeGradation << " " << _volumeGradation;
 
   op_val = _option2value.begin();
   if (op_val != _option2value.end()) {
@@ -1481,16 +2175,6 @@ std::ostream & BLSURFPlugin_Hypothesis::SaveTo(std::ostream & save) {
     save << " " << "__PRECAD_OPTIONS_END__";
   }
 
-  op_val = _customPreCADOption2value.begin();
-  if (op_val != _customPreCADOption2value.end()) {
-    save << " " << "__CUSTOM_PRECAD_OPTIONS_BEGIN__";
-    for (; op_val != _customPreCADOption2value.end(); ++op_val) {
-      if (!op_val->second.empty())
-        save << " " << op_val->first << " " << op_val->second << "%#"; // "%#" is a mark of value end
-    }
-    save << " " << "__CUSTOM_PRECAD_OPTIONS_END__";
-  }
-
   TSizeMap::iterator it_sm = _sizeMap.begin();
   if (it_sm != _sizeMap.end()) {
     save << " " << "__SIZEMAP_BEGIN__";
@@ -1529,7 +2213,6 @@ std::ostream & BLSURFPlugin_Hypothesis::SaveTo(std::ostream & save) {
     }
     save << " " << "__NEW_ATTRACTORS_END__";
     test << " " << "__NEW_ATTRACTORS_END__";
-    MESSAGE(" Attractor hypothesis saved as "<<test.str())
   }
 
   TEnfVertexList::const_iterator it_enf = _enfVertexList.begin();
@@ -1566,7 +2249,10 @@ std::ostream & BLSURFPlugin_Hypothesis::SaveTo(std::ostream & save) {
         save << " " << "__BEGIN_FACELIST__";
       }
       for (; faceEntriesIt != enfVertex->faceEntries.end(); ++faceEntriesIt)
-        save << " " << (*faceEntriesIt);
+        if ( faceEntriesIt->empty() )
+          save << " _no_face_";
+        else
+          save << " " << (*faceEntriesIt);
       if (hasFaces)
         save << " " << "__END_FACELIST__";
       save << " " << "__END_VERTEX__";
@@ -1583,14 +2269,39 @@ std::ostream & BLSURFPlugin_Hypothesis::SaveTo(std::ostream & save) {
   SaveEdgesPeriodicity(save);
   SaveVerticesPeriodicity(save);
 
+  // HYPER-PATCHES
+  save << " " << _hyperPatchList.size() << " ";
+  for ( size_t i = 0; i < _hyperPatchList.size(); ++i )
+  {
+    THyperPatchTags& patch = _hyperPatchList[i];
+    save << patch.size() << " ";
+    THyperPatchTags::iterator tag = patch.begin();
+    for ( ; tag != patch.end(); ++tag )
+      save << *tag << " ";
+  }
+
+  // New options in 2.9.6 (issue #17784)
+  save << " " << _useSurfaceProximity;
+  save << " " << _nbSurfaceProximityLayers;
+  save << " " << _surfaceProximityRatio;
+  save << " " << _useVolumeProximity;
+  save << " " << _nbVolumeProximityLayers;
+  save << " " << _volumeProximityRatio;
+
+  // hyper-patches as entries
+  std::ostringstream hpStream;
+  boost::archive::text_oarchive( hpStream ) << _hyperPatchEntriesList;
+  std::string hpString = hpStream.str();
+  save << " " << hpString.size() <<  " " << hpString;
+
+
   return save;
 }
 
-void BLSURFPlugin_Hypothesis::SaveFacesPeriodicity(std::ostream & save){
-
+void BLSURFPlugin_Hypothesis::SaveFacesPeriodicity(std::ostream & save)
+{
   TFacesPeriodicityVector::const_iterator it_faces_periodicity = _facesPeriodicityVector.begin();
   if (it_faces_periodicity != _facesPeriodicityVector.end()) {
-    MESSAGE("__FACES_PERIODICITY_BEGIN__");
     save << " " << "__FACES_PERIODICITY_BEGIN__";
     for (; it_faces_periodicity != _facesPeriodicityVector.end(); ++it_faces_periodicity) {
       TFacesPeriodicity periodicity_i = (*it_faces_periodicity);
@@ -1604,16 +2315,14 @@ void BLSURFPlugin_Hypothesis::SaveFacesPeriodicity(std::ostream & save){
       save << " " << "__END_PERIODICITY_DESCRIPTION__";
     }
     save << " " << "__FACES_PERIODICITY_END__";
-    MESSAGE("__FACES_PERIODICITY_END__");
   }
 }
 
-void BLSURFPlugin_Hypothesis::SaveEdgesPeriodicity(std::ostream & save){
-
+void BLSURFPlugin_Hypothesis::SaveEdgesPeriodicity(std::ostream & save)
+{
   TEdgesPeriodicityVector::const_iterator it_edges_periodicity = _edgesPeriodicityVector.begin();
   if (it_edges_periodicity != _edgesPeriodicityVector.end()) {
     save << " " << "__EDGES_PERIODICITY_BEGIN__";
-    MESSAGE("__EDGES_PERIODICITY_BEGIN__");
     for (; it_edges_periodicity != _edgesPeriodicityVector.end(); ++it_edges_periodicity) {
       TEdgePeriodicity periodicity_i = (*it_edges_periodicity);
       save << " " << "__BEGIN_PERIODICITY_DESCRIPTION__";
@@ -1639,15 +2348,13 @@ void BLSURFPlugin_Hypothesis::SaveEdgesPeriodicity(std::ostream & save){
       save << " " << "__END_PERIODICITY_DESCRIPTION__";
     }
     save << " " << "__EDGES_PERIODICITY_END__";
-    MESSAGE("__EDGES_PERIODICITY_END__");
   }
 }
 
-void BLSURFPlugin_Hypothesis::SaveVerticesPeriodicity(std::ostream & save){
-
+void BLSURFPlugin_Hypothesis::SaveVerticesPeriodicity(std::ostream & save)
+{
   TVerticesPeriodicityVector::const_iterator it_vertices_periodicity = _verticesPeriodicityVector.begin();
   if (it_vertices_periodicity != _verticesPeriodicityVector.end()) {
-    MESSAGE("__VERTICES_PERIODICITY_BEGIN__");
     save << " " << "__VERTICES_PERIODICITY_BEGIN__";
     for (; it_vertices_periodicity != _verticesPeriodicityVector.end(); ++it_vertices_periodicity) {
       TVertexPeriodicity periodicity_i = (*it_vertices_periodicity);
@@ -1667,11 +2374,11 @@ void BLSURFPlugin_Hypothesis::SaveVerticesPeriodicity(std::ostream & save){
       save << " " << "__END_PERIODICITY_DESCRIPTION__";
     }
     save << " " << "__VERTICES_PERIODICITY_END__";
-    MESSAGE("__VERTICES_PERIODICITY_END__");
   }
 }
 
-void BLSURFPlugin_Hypothesis::SavePreCADPeriodicity(std::ostream & save, const char* shapeType) {
+void BLSURFPlugin_Hypothesis::SavePreCADPeriodicity(std::ostream & save, const char* shapeType)
+{
   TPreCadPeriodicityVector precad_periodicity;
   if ( shapeType  &&  strcmp( shapeType, "FACES" ) == 0 )
     precad_periodicity = _preCadFacesPeriodicityVector;
@@ -1724,7 +2431,8 @@ void BLSURFPlugin_Hypothesis::SavePreCADPeriodicity(std::ostream & save, const c
 }
 
 //=============================================================================
-std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
+std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load)
+{
   bool isOK = true;
   int i;
   double val;
@@ -1768,7 +2476,7 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
 
   isOK = static_cast<bool>(load >> i);
   if (isOK)
-    _quadAllowed = (bool) i;
+    _elementType = (ElementType) i;
   else
     load.clear(std::ios::badbit | load.rdstate());
 
@@ -1869,7 +2577,6 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
   bool hasOptions = false;
   bool hasCustomOptions = false;
   bool hasPreCADOptions = false;
-  bool hasCustomPreCADOptions = false;
   bool hasSizeMap = false;
   bool hasAttractor = false;
   bool hasNewAttractor = false;
@@ -1881,20 +2588,18 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
   bool hasVerticesPeriodicity = false;
 
   isOK = static_cast<bool>(load >> option_or_sm);
-  if (isOK)
-    if ( (option_or_sm == "1")||(option_or_sm == "0") ) {
+  if (isOK) {
+    if (( option_or_sm == "1" ) || ( option_or_sm == "0" )) {
       i = atoi(option_or_sm.c_str());
       hasCADSurfOptions = true;
       _phySizeRel = (bool) i;
     }
-    if (option_or_sm == "__OPTIONS_BEGIN__")
+    else if (option_or_sm == "__OPTIONS_BEGIN__")
       hasOptions = true;
     else if (option_or_sm == "__CUSTOM_OPTIONS_BEGIN__")
       hasCustomOptions = true;
     else if (option_or_sm == "__PRECAD_OPTIONS_BEGIN__")
       hasPreCADOptions = true;
-    else if (option_or_sm == "__CUSTOM_PRECAD_OPTIONS_BEGIN__")
-      hasCustomPreCADOptions = true;
     else if (option_or_sm == "__SIZEMAP_BEGIN__")
       hasSizeMap = true;
     else if (option_or_sm == "__ATTRACTORS_BEGIN__")
@@ -1913,6 +2618,7 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
       hasEdgesPeriodicity = true;
     else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
       hasVerticesPeriodicity = true;
+  }
 
   if (isOK && hasCADSurfOptions) {
     isOK = static_cast<bool>(load >> i);
@@ -1987,8 +2693,58 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
     else
       load.clear(std::ios::badbit | load.rdstate());
 
+    if (( load >> std::ws).peek() != '_' )
+    {
+      isOK = static_cast<bool>(load >> i);
+      if (isOK)
+        _preCADRemoveDuplicateCADFaces = (bool) i;
+      else
+        load.clear(std::ios::badbit | load.rdstate());
+
+      isOK = static_cast<bool>(load >> i);
+      if (isOK)
+        _optimiseTinyEdges = (bool) i;
+      else
+        load.clear(std::ios::badbit | load.rdstate());
+
+      isOK = static_cast<bool>(load >> val);
+      if (isOK)
+        _tinyEdgeOptimisationLength = val;
+      else
+        load.clear(std::ios::badbit | load.rdstate());
+
+      isOK = static_cast<bool>(load >> i);
+      if (isOK)
+        _correctSurfaceIntersec = (bool) i;
+      else
+        load.clear(std::ios::badbit | load.rdstate());
+
+      isOK = static_cast<bool>(load >> val);
+      if (isOK)
+        _corrSurfaceIntersCost = val;
+      else
+        load.clear(std::ios::badbit | load.rdstate());
+
+      isOK = static_cast<bool>(load >> i);
+      if (isOK)
+        _useGradation = (bool) i;
+      else
+        load.clear(std::ios::badbit | load.rdstate());
+
+      isOK = static_cast<bool>(load >> i);
+      if (isOK)
+        _useVolumeGradation = (bool) i;
+      else
+        load.clear(std::ios::badbit | load.rdstate());
+
+      isOK = static_cast<bool>(load >> val);
+      if (isOK)
+        _volumeGradation = val;
+      else
+        load.clear(std::ios::badbit | load.rdstate());
+    }
   }
-  
+
 
   if (hasCADSurfOptions) {
     isOK = static_cast<bool>(load >> option_or_sm);
@@ -1999,8 +2755,6 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
         hasCustomOptions = true;
       else if (option_or_sm == "__PRECAD_OPTIONS_BEGIN__")
         hasPreCADOptions = true;
-      else if (option_or_sm == "__CUSTOM_PRECAD_OPTIONS_BEGIN__")
-        hasCustomPreCADOptions = true;
       else if (option_or_sm == "__SIZEMAP_BEGIN__")
         hasSizeMap = true;
       else if (option_or_sm == "__ATTRACTORS_BEGIN__")
@@ -2030,22 +2784,29 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
         break;
       isOK = static_cast<bool>(load >> optValue);
     }
-    if (isOK) {
+    // read the value of the advanced option
+    // unless this option is no more used
+    if (isOK
+#if MESHGEMS_VERSION_HEX >= 0x020A00
+        && optName != "enforce_cad_edge_sizes" && optName != "max_number_of_points_per_patch"
+#endif
+        ) {
       std::string & value = _option2value[optName];
       value = optValue;
-      int len = value.size();
+      int len = (int) value.size();
       // continue reading until "%#" encountered
       while (value[len - 1] != '#' || value[len - 2] != '%') {
         isOK = static_cast<bool>(load >> optValue);
         if (isOK) {
           value += " ";
           value += optValue;
-          len = value.size();
+          len = (int) value.size();
         } else {
           break;
         }
       }
-      value[len - 2] = '\0'; //cut off "%#"
+      if ( value[ len - 1] == '#' )
+        value.resize(len - 2); //cut off "%#"
     }
   }
 
@@ -2056,8 +2817,6 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
         hasCustomOptions = true;
       else if (option_or_sm == "__PRECAD_OPTIONS_BEGIN__")
         hasPreCADOptions = true;
-      else if (option_or_sm == "__CUSTOM_PRECAD_OPTIONS_BEGIN__")
-        hasCustomPreCADOptions = true;
       else if (option_or_sm == "__SIZEMAP_BEGIN__")
         hasSizeMap = true;
       else if (option_or_sm == "__ATTRACTORS_BEGIN__")
@@ -2088,20 +2847,21 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
     }
     if (isOK) {
       std::string& value = optValue;
-      int len = value.size();
+      int len = (int) value.size();
       // continue reading until "%#" encountered
       while (value[len - 1] != '#' || value[len - 2] != '%') {
         isOK = static_cast<bool>(load >> optValue);
         if (isOK) {
           value += " ";
           value += optValue;
-          len = value.size();
+          len = (int) value.size();
         } else {
           break;
         }
       }
-      _customOption2value[optName] = value.substr(0,len-2);
-      value[len - 2] = '\0'; //cut off "%#"
+      if ( value[ len - 1] == '#' )
+        value.resize(len - 2); //cut off "%#"
+      _customOption2value[optName] = value;
     }
   }
 
@@ -2110,8 +2870,6 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
     if (isOK) {
       if (option_or_sm == "__PRECAD_OPTIONS_BEGIN__")
         hasPreCADOptions = true;
-      else if (option_or_sm == "__CUSTOM_PRECAD_OPTIONS_BEGIN__")
-        hasCustomPreCADOptions = true;
       else if (option_or_sm == "__SIZEMAP_BEGIN__")
         hasSizeMap = true;
       else if (option_or_sm == "__ATTRACTORS_BEGIN__")
@@ -2143,75 +2901,24 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
     if (isOK) {
       std::string & value = _preCADoption2value[optName];
       value = optValue;
-      int len = value.size();
+      int len = (int) value.size();
       // continue reading until "%#" encountered
       while (value[len - 1] != '#' || value[len - 2] != '%') {
         isOK = static_cast<bool>(load >> optValue);
         if (isOK) {
           value += " ";
           value += optValue;
-          len = value.size();
+          len = (int) value.size();
         } else {
           break;
         }
       }
-      value[len - 2] = '\0'; //cut off "%#"
+      if ( value[ len - 1] == '#' )
+        value.resize(len - 2); //cut off "%#"
     }
   }
 
   if (hasPreCADOptions) {
-    isOK = static_cast<bool>(load >> option_or_sm);
-    if (isOK) {
-      if (option_or_sm == "__CUSTOM_PRECAD_OPTIONS_BEGIN__")
-        hasCustomPreCADOptions = true;
-      else if (option_or_sm == "__SIZEMAP_BEGIN__")
-        hasSizeMap = true;
-      else if (option_or_sm == "__ATTRACTORS_BEGIN__")
-        hasAttractor = true;
-      else if (option_or_sm == "__NEW_ATTRACTORS_BEGIN__")
-        hasNewAttractor = true;
-      else if (option_or_sm == "__ENFORCED_VERTICES_BEGIN__")
-        hasEnforcedVertex = true;
-      else if (option_or_sm == "__PRECAD_FACES_PERIODICITY_BEGIN__")
-        hasPreCADFacesPeriodicity = true;
-      else if (option_or_sm == "__PRECAD_EDGES_PERIODICITY_BEGIN__")
-        hasPreCADEdgesPeriodicity = true;
-      else if (option_or_sm == "__FACES_PERIODICITY_BEGIN__")
-        hasFacesPeriodicity = true;
-      else if (option_or_sm == "__EDGES_PERIODICITY_BEGIN__")
-        hasEdgesPeriodicity = true;
-      else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
-        hasVerticesPeriodicity = true;
-    }
-  }
-
-  while (isOK && hasCustomPreCADOptions) {
-    isOK = static_cast<bool>(load >> optName);
-    if (isOK) {
-      if (optName == "__CUSTOM_PRECAD_OPTIONS_END__")
-        break;
-      isOK = static_cast<bool>(load >> optValue);
-    }
-    if (isOK) {
-      std::string& value = optValue;
-      int len = value.size();
-      // continue reading until "%#" encountered
-      while (value[len - 1] != '#' || value[len - 2] != '%') {
-        isOK = static_cast<bool>(load >> optValue);
-        if (isOK) {
-          value += " ";
-          value += optValue;
-          len = value.size();
-        } else {
-          break;
-        }
-      }
-      _customPreCADOption2value[optName] = value.substr(0,len-2);
-      value[len - 2] = '\0'; //cut off "%#"
-    }
-  }
-
-  if (hasCustomPreCADOptions) {
     isOK = static_cast<bool>(load >> option_or_sm);
     if (isOK) {
       if (option_or_sm == "__SIZEMAP_BEGIN__")
@@ -2234,7 +2941,7 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
         hasVerticesPeriodicity = true;
     }
   }
-  
   std::string smEntry, smValue;
   while (isOK && hasSizeMap) {
     isOK = static_cast<bool>(load >> smEntry);
@@ -2246,28 +2953,28 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
     if (isOK) {
       std::string & value2 = _sizeMap[smEntry];
       value2 = smValue;
-      int len2 = value2.size();
+      int len2 = (int) value2.size();
       // continue reading until "%#" encountered
       while (value2[len2 - 1] != '#' || value2[len2 - 2] != '%') {
         isOK = static_cast<bool>(load >> smValue);
         if (isOK) {
           value2 += " ";
           value2 += smValue;
-          len2 = value2.size();
+          len2 = (int) value2.size();
         } else {
           break;
         }
       }
-      value2[len2 - 2] = '\0'; //cut off "%#"
+      value2.resize(len2 - 2); //cut off "%#"
     }
   }
 
   if (hasSizeMap) {
     isOK = static_cast<bool>(load >> option_or_sm);
-    if (isOK)
+    if (isOK) {
       if (option_or_sm == "__ATTRACTORS_BEGIN__")
         hasAttractor = true;
-      if (option_or_sm == "__NEW_ATTRACTORS_BEGIN__")
+      else if (option_or_sm == "__NEW_ATTRACTORS_BEGIN__")
         hasNewAttractor = true;
       else if (option_or_sm == "__ENFORCED_VERTICES_BEGIN__")
         hasEnforcedVertex = true;
@@ -2281,6 +2988,7 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
         hasEdgesPeriodicity = true;
       else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
         hasVerticesPeriodicity = true;
+    }
   }
 
   std::string atEntry, atValue;
@@ -2294,19 +3002,19 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
     if (isOK) {
       std::string & value3 = _attractors[atEntry];
       value3 = atValue;
-      int len3 = value3.size();
+      int len3 = (int) value3.size();
       // continue reading until "%#" encountered
       while (value3[len3 - 1] != '#' || value3[len3 - 2] != '%') {
         isOK = static_cast<bool>(load >> atValue);
         if (isOK) {
           value3 += " ";
           value3 += atValue;
-          len3 = value3.size();
+          len3 = (int) value3.size();
         } else {
           break;
         }
       }
-      value3[len3 - 2] = '\0'; //cut off "%#"
+      value3.resize(len3 - 2); //cut off "%#"
     }
   }
 
@@ -2342,11 +3050,10 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
         break;
       isOK = static_cast<bool>(load >> newAtShapeEntry);
       if (!isOK)
-    break;
+        break;
       isOK = static_cast<bool>(load >> attParams[0]>>attParams[1]>>attParams[2]>>attParams[3]); //>>step);
     }
     if (isOK) {
-      MESSAGE(" LOADING ATTRACTOR HYPOTHESIS ")
       const TopoDS_Shape attractorShape = BLSURFPlugin_Hypothesis::entryToShape(newAtShapeEntry);
       const TopoDS_Face faceShape = TopoDS::Face(BLSURFPlugin_Hypothesis::entryToShape(newAtFaceEntry));
       BLSURFPlugin_Attractor* attractor = new BLSURFPlugin_Attractor(faceShape, attractorShape, newAtShapeEntry);//, step);
@@ -2381,17 +3088,17 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
 // __ENFORCED_VERTICES_BEGIN__ 
 // __BEGIN_VERTEX__  => no name, no entry
 // __BEGIN_GROUP__ mon groupe __END_GROUP__
-// __BEGIN_COORDS__ 10 10 10 __END_COORDS__ 
-// __BEGIN_FACELIST__ 0:1:1:1:1 __END_FACELIST__ 
-// __END_VERTEX__ 
+// __BEGIN_COORDS__ 10 10 10 __END_COORDS__
+// __BEGIN_FACELIST__ 0:1:1:1:1 __END_FACELIST__
+// __END_VERTEX__
 // __BEGIN_VERTEX__ => no coords
-// __BEGIN_NAME__ mes points __END_NAME__ 
+// __BEGIN_NAME__ mes points __END_NAME__
 // __BEGIN_ENTRY__ 0:1:1:4 __END_ENTRY__
 // __BEGIN_GROUP__ mon groupe __END_GROUP__
 // __BEGIN_FACELIST__ 0:1:1:1:3 __END_FACELIST__
-// __END_VERTEX__ 
+// __END_VERTEX__
 // __ENFORCED_VERTICES_END__
-// 
+//
 
   std::string enfSeparator;
   std::string enfName;
@@ -2400,29 +3107,28 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
   TEntryList enfFaceEntryList;
   double enfCoords[3];
   bool hasCoords = false;
-  
+
   _faceEntryEnfVertexListMap.clear();
   _enfVertexList.clear();
   _faceEntryCoordsListMap.clear();
   _coordsEnfVertexMap.clear();
   _faceEntryEnfVertexEntryListMap.clear();
   _enfVertexEntryEnfVertexMap.clear();
-  
-  
-  while (isOK && hasEnforcedVertex) {
+
+
+  while (isOK && hasEnforcedVertex)
+  {
     isOK = static_cast<bool>(load >> enfSeparator); // __BEGIN_VERTEX__
     TEnfVertex *enfVertex = new TEnfVertex();
-//     MESSAGE("enfSeparator: " <<enfSeparator);
     if (enfSeparator == "__ENFORCED_VERTICES_END__")
       break; // __ENFORCED_VERTICES_END__
     if (enfSeparator != "__BEGIN_VERTEX__")
       throw std::exception();
-    
+
     while (isOK) {
       isOK = static_cast<bool>(load >> enfSeparator);
-      MESSAGE("enfSeparator: " <<enfSeparator);
       if (enfSeparator == "__END_VERTEX__") {
-        
+
         enfVertex->name = enfName;
         enfVertex->geomEntry = enfGeomEntry;
         enfVertex->grpName = enfGroup;
@@ -2430,9 +3136,9 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
         if (hasCoords)
           enfVertex->coords.assign(enfCoords,enfCoords+3);
         enfVertex->faceEntries = enfFaceEntryList;
-        
+
         _enfVertexList.insert(enfVertex);
-        
+
         if (enfVertex->coords.size()) {
           _coordsEnfVertexMap[enfVertex->coords] = enfVertex;
           for (TEntryList::const_iterator it = enfVertex->faceEntries.begin() ; it != enfVertex->faceEntries.end(); ++it) {
@@ -2447,7 +3153,7 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
             _faceEntryEnfVertexListMap[(*it)].insert(enfVertex);
           }
         }
-        
+
         enfName.clear();
         enfGeomEntry.clear();
         enfGroup.clear();
@@ -2455,7 +3161,7 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
         hasCoords = false;
         break; // __END_VERTEX__
       }
-        
+
       if (enfSeparator == "__BEGIN_NAME__") {  // __BEGIN_NAME__
         while (isOK && (enfSeparator != "__END_NAME__")) {
           isOK = static_cast<bool>(load >> enfSeparator);
@@ -2465,17 +3171,15 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
             enfName += enfSeparator;
           }
         }
-        MESSAGE("enfName: " <<enfName);
       }
-        
+
       if (enfSeparator == "__BEGIN_ENTRY__") {  // __BEGIN_ENTRY__
         isOK = static_cast<bool>(load >> enfGeomEntry);
         isOK = static_cast<bool>(load >> enfSeparator); // __END_ENTRY__
         if (enfSeparator != "__END_ENTRY__")
           throw std::exception();
-        MESSAGE("enfGeomEntry: " <<enfGeomEntry);
       }
-        
+
       if (enfSeparator == "__BEGIN_GROUP__") {  // __BEGIN_GROUP__
         while (isOK && (enfSeparator != "__END_GROUP__")) {
           isOK = static_cast<bool>(load >> enfSeparator);
@@ -2485,33 +3189,47 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
             enfGroup += enfSeparator;
           }
         }
-        MESSAGE("enfGroup: " <<enfGroup);
       }
-        
+
       if (enfSeparator == "__BEGIN_COORDS__") {  // __BEGIN_COORDS__
         hasCoords = true;
         isOK = static_cast<bool>(load >> enfCoords[0] >> enfCoords[1] >> enfCoords[2]);
         isOK = static_cast<bool>(load >> enfSeparator); // __END_COORDS__
         if (enfSeparator != "__END_COORDS__")
           throw std::exception();
-        MESSAGE("enfCoords: " << enfCoords[0] <<","<< enfCoords[1] <<","<< enfCoords[2]);
-      } 
-        
+      }
+
       if (enfSeparator == "__BEGIN_FACELIST__") {  // __BEGIN_FACELIST__
         while (isOK && (enfSeparator != "__END_FACELIST__")) {
           isOK = static_cast<bool>(load >> enfSeparator);
           if (enfSeparator != "__END_FACELIST__") {
             enfFaceEntryList.insert(enfSeparator);
-            MESSAGE(enfSeparator << " was inserted into enfFaceEntryList");
           }
         }
-      } 
+      }
+    }
+  }
+
+  if ( hasEnforcedVertex ) {
+    isOK = static_cast<bool>(load >> option_or_sm);
+    if (isOK) {
+      if (option_or_sm == "__PRECAD_FACES_PERIODICITY_BEGIN__")
+        hasPreCADFacesPeriodicity = true;
+      else if (option_or_sm == "__PRECAD_EDGES_PERIODICITY_BEGIN__")
+        hasPreCADEdgesPeriodicity = true;
+      else if (option_or_sm == "__FACES_PERIODICITY_BEGIN__")
+        hasFacesPeriodicity = true;
+      else if (option_or_sm == "__EDGES_PERIODICITY_BEGIN__")
+        hasEdgesPeriodicity = true;
+      else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
+        hasVerticesPeriodicity = true;
     }
   }
 
   // PERIODICITY
 
-  if (hasPreCADFacesPeriodicity){
+  if (hasPreCADFacesPeriodicity)
+  {
     LoadPreCADPeriodicity(load, "FACES");
 
     isOK = static_cast<bool>(load >> option_or_sm);
@@ -2527,7 +3245,8 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
     }
   }
 
-  if (hasPreCADEdgesPeriodicity){
+  if (hasPreCADEdgesPeriodicity)
+  {
     LoadPreCADPeriodicity(load, "EDGES");
 
     isOK = static_cast<bool>(load >> option_or_sm);
@@ -2541,8 +3260,9 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
     }
   }
 
-  if (hasFacesPeriodicity){
-      LoadFacesPeriodicity(load);
+  if (hasFacesPeriodicity)
+  {
+    LoadFacesPeriodicity(load);
 
     isOK = static_cast<bool>(load >> option_or_sm);
     if (isOK) {
@@ -2553,8 +3273,9 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
     }
   }
 
-  if (hasEdgesPeriodicity){
-      LoadEdgesPeriodicity(load);
+  if (hasEdgesPeriodicity)
+  {
+    LoadEdgesPeriodicity(load);
 
     isOK = static_cast<bool>(load >> option_or_sm);
     if (isOK)
@@ -2563,13 +3284,69 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
   }
 
   if (hasVerticesPeriodicity)
-      LoadVerticesPeriodicity(load);
+    LoadVerticesPeriodicity(load);
+
+  // HYPER-PATCHES
+  if ( !option_or_sm.empty() && option_or_sm[0] == '_' )
+    isOK = static_cast<bool>(load >> option_or_sm);
+  if ( isOK && !option_or_sm.empty() )
+  {
+    int nbPatches = atoi( option_or_sm.c_str() );
+    if ( nbPatches >= 0 )
+    {
+      _hyperPatchList.resize( nbPatches );
+      for ( int iP = 0; iP < nbPatches && isOK; ++iP )
+      {
+        isOK = static_cast<bool>(load >> i) && i >= 2;
+        if ( !isOK ) break;
+        int nbTags = i;
+        for ( int iT = 0; iT < nbTags; ++iT )
+        {
+          if (( isOK = static_cast<bool>(load >> i)))
+            _hyperPatchList[ iP ].insert( i );
+          else
+            break;
+        }
+      }
+      if ( !isOK ) // remove invalid patches
+      {
+        for ( i = nbPatches - 1; i >= 0; i-- )
+          if ( _hyperPatchList[i].size() < 2 )
+            _hyperPatchList.resize( i );
+      }
+    }
+  }
+
+  // New options in 2.9.6 (issue #17784)
+  if ( static_cast<bool>( load >> _useSurfaceProximity ))
+  {
+    load >> _nbSurfaceProximityLayers;
+    load >> _surfaceProximityRatio;
+    load >> _useVolumeProximity;
+    load >> _nbVolumeProximityLayers;
+    isOK = static_cast<bool>( load >> _volumeProximityRatio );
+  }
+
+  // hyper-patches as entries (issue bos #20543)
+  if ( static_cast<bool>( load >> i ) && i > 0 )
+  {
+    std::string buffer( i, '\0' );
+    load.get( buffer[0] ); // remove a white-space
+    load.get( & buffer[0], i + 1 );
+
+    std::istringstream istream( buffer.data() );
+    boost::archive::text_iarchive archive( istream );
+    try {
+      archive >> _hyperPatchEntriesList;
+    }
+    catch (...) {}
+  }
 
   return load;
 }
 
-void BLSURFPlugin_Hypothesis::LoadFacesPeriodicity(std::istream & load){
-
+void BLSURFPlugin_Hypothesis::LoadFacesPeriodicity(std::istream & load)
+{
   bool isOK = true;
 
   std::string periodicitySeparator;
@@ -2580,18 +3357,15 @@ void BLSURFPlugin_Hypothesis::LoadFacesPeriodicity(std::istream & load){
 
   while (isOK) {
     isOK = static_cast<bool>(load >> periodicitySeparator); // __BEGIN_PERIODICITY_DESCRIPTION__
-    MESSAGE("periodicitySeparator 1: " <<periodicitySeparator);
     TFacesPeriodicity *periodicity_i = new TFacesPeriodicity();
     if (periodicitySeparator == "__FACES_PERIODICITY_END__")
       break; // __FACES_PERIODICITY_END__
     if (periodicitySeparator != "__BEGIN_PERIODICITY_DESCRIPTION__"){
-      MESSAGE("//" << periodicitySeparator << "//");
       throw std::exception();
     }
 
     while (isOK) {
       isOK = static_cast<bool>(load >> periodicitySeparator);
-      MESSAGE("periodicitySeparator 2: " <<periodicitySeparator);
       if (periodicitySeparator == "__END_PERIODICITY_DESCRIPTION__") {
 
         periodicity_i->first = shape1Entry;
@@ -2607,7 +3381,6 @@ void BLSURFPlugin_Hypothesis::LoadFacesPeriodicity(std::istream & load){
         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_ENTRY1__
         if (periodicitySeparator != "__END_ENTRY1__")
           throw std::exception();
-        MESSAGE("shape1Entry: " <<shape1Entry);
       }
 
       if (periodicitySeparator == "__BEGIN_ENTRY2__") {  // __BEGIN_ENTRY2__
@@ -2615,15 +3388,14 @@ void BLSURFPlugin_Hypothesis::LoadFacesPeriodicity(std::istream & load){
         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_ENTRY2__
         if (periodicitySeparator != "__END_ENTRY2__")
           throw std::exception();
-        MESSAGE("shape2Entry: " <<shape2Entry);
       }
     }
   }
 }
 
 
-void BLSURFPlugin_Hypothesis::LoadEdgesPeriodicity(std::istream & load){
-
+void BLSURFPlugin_Hypothesis::LoadEdgesPeriodicity(std::istream & load)
+{
   bool isOK = true;
 
   std::string periodicitySeparator;
@@ -2637,18 +3409,15 @@ void BLSURFPlugin_Hypothesis::LoadEdgesPeriodicity(std::istream & load){
 
   while (isOK) {
     isOK = static_cast<bool>(load >> periodicitySeparator); // __BEGIN_PERIODICITY_DESCRIPTION__
-    MESSAGE("periodicitySeparator 1: " <<periodicitySeparator);
     TEdgePeriodicity *periodicity_i = new TEdgePeriodicity();
     if (periodicitySeparator == "__EDGES_PERIODICITY_END__")
       break; // __EDGES_PERIODICITY_END__
     if (periodicitySeparator != "__BEGIN_PERIODICITY_DESCRIPTION__"){
-      MESSAGE("//" << periodicitySeparator << "//");
       throw std::exception();
     }
 
     while (isOK) {
       isOK = static_cast<bool>(load >> periodicitySeparator);
-      MESSAGE("periodicitySeparator 2: " <<periodicitySeparator);
       if (periodicitySeparator == "__END_PERIODICITY_DESCRIPTION__") {
 
         periodicity_i->theFace1Entry = theFace1Entry;
@@ -2664,13 +3433,10 @@ void BLSURFPlugin_Hypothesis::LoadEdgesPeriodicity(std::istream & load){
 
       if (periodicitySeparator == "__BEGIN_FACE1__") {  // __BEGIN_FACE1__
         isOK = static_cast<bool>(load >> theFace1Entry);
-        MESSAGE("//" << theFace1Entry << "//");
         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_FACE1__
         if (periodicitySeparator != "__END_FACE1__"){
-          MESSAGE("//" << periodicitySeparator << "//");
           throw std::exception();
         }
-        MESSAGE("theFace1Entry: " <<theFace1Entry);
       }
 
       if (periodicitySeparator == "__BEGIN_EDGE1__") {  // __BEGIN_EDGE1__
@@ -2678,7 +3444,6 @@ void BLSURFPlugin_Hypothesis::LoadEdgesPeriodicity(std::istream & load){
         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_EDGE1__
         if (periodicitySeparator != "__END_EDGE1__")
           throw std::exception();
-        MESSAGE("theEdge1Entry: " <<theEdge1Entry);
       }
 
       if (periodicitySeparator == "__BEGIN_FACE2__") {  // __BEGIN_FACE2__
@@ -2686,7 +3451,6 @@ void BLSURFPlugin_Hypothesis::LoadEdgesPeriodicity(std::istream & load){
         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_FACE2__
         if (periodicitySeparator != "__END_FACE2__")
           throw std::exception();
-        MESSAGE("theFace2Entry: " <<theFace2Entry);
       }
 
       if (periodicitySeparator == "__BEGIN_EDGE2__") {  // __BEGIN_EDGE2__
@@ -2694,7 +3458,6 @@ void BLSURFPlugin_Hypothesis::LoadEdgesPeriodicity(std::istream & load){
         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_EDGE2__
         if (periodicitySeparator != "__END_EDGE2__")
           throw std::exception();
-        MESSAGE("theEdge2Entry: " <<theEdge2Entry);
       }
 
       if (periodicitySeparator == "__BEGIN_EDGE_ORIENTATION__") {  // __BEGIN_EDGE_ORIENTATION__
@@ -2702,14 +3465,13 @@ void BLSURFPlugin_Hypothesis::LoadEdgesPeriodicity(std::istream & load){
         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_EDGE_ORIENTATION__
         if (periodicitySeparator != "__END_EDGE_ORIENTATION__")
           throw std::exception();
-        MESSAGE("edge_orientation: " <<edge_orientation);
       }
     }
   }
 }
 
-void BLSURFPlugin_Hypothesis::LoadVerticesPeriodicity(std::istream & load){
-
+void BLSURFPlugin_Hypothesis::LoadVerticesPeriodicity(std::istream & load)
+{
   bool isOK = true;
 
   std::string periodicitySeparator;
@@ -2722,18 +3484,15 @@ void BLSURFPlugin_Hypothesis::LoadVerticesPeriodicity(std::istream & load){
 
   while (isOK) {
     isOK = static_cast<bool>(load >> periodicitySeparator); // __BEGIN_PERIODICITY_DESCRIPTION__
-    MESSAGE("periodicitySeparator 1: " <<periodicitySeparator);
     TVertexPeriodicity *periodicity_i = new TVertexPeriodicity();
     if (periodicitySeparator == "__VERTICES_PERIODICITY_END__")
       break; // __VERTICES_PERIODICITY_END__
     if (periodicitySeparator != "__BEGIN_PERIODICITY_DESCRIPTION__"){
-      MESSAGE("//" << periodicitySeparator << "//");
       throw std::exception();
     }
 
     while (isOK) {
       isOK = static_cast<bool>(load >> periodicitySeparator);
-      MESSAGE("periodicitySeparator 2: " <<periodicitySeparator);
       if (periodicitySeparator == "__END_PERIODICITY_DESCRIPTION__") {
 
         periodicity_i->theEdge1Entry = theEdge1Entry;
@@ -2751,7 +3510,6 @@ void BLSURFPlugin_Hypothesis::LoadVerticesPeriodicity(std::istream & load){
         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_EDGE1__
         if (periodicitySeparator != "__END_EDGE1__")
           throw std::exception();
-        MESSAGE("theEdge1Entry: " <<theEdge1Entry);
       }
 
       if (periodicitySeparator == "__BEGIN_VERTEX1__") {  // __BEGIN_VERTEX1__
@@ -2759,7 +3517,6 @@ void BLSURFPlugin_Hypothesis::LoadVerticesPeriodicity(std::istream & load){
         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_VERTEX1__
         if (periodicitySeparator != "__END_VERTEX1__")
           throw std::exception();
-        MESSAGE("theVertex1Entry: " <<theVertex1Entry);
       }
 
       if (periodicitySeparator == "__BEGIN_EDGE2__") {  // __BEGIN_EDGE2__
@@ -2767,7 +3524,6 @@ void BLSURFPlugin_Hypothesis::LoadVerticesPeriodicity(std::istream & load){
         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_EDGE2__
         if (periodicitySeparator != "__END_EDGE2__")
           throw std::exception();
-        MESSAGE("theEdge2Entry: " <<theEdge2Entry);
       }
 
       if (periodicitySeparator == "__BEGIN_VERTEX2__") {  // __BEGIN_VERTEX2__
@@ -2775,14 +3531,13 @@ void BLSURFPlugin_Hypothesis::LoadVerticesPeriodicity(std::istream & load){
         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_VERTEX2__
         if (periodicitySeparator != "__END_VERTEX2__")
           throw std::exception();
-        MESSAGE("theVertex2Entry: " <<theVertex2Entry);
       }
     }
   }
 }
 
-void BLSURFPlugin_Hypothesis::LoadPreCADPeriodicity(std::istream & load, const char* shapeType) {
-
+void BLSURFPlugin_Hypothesis::LoadPreCADPeriodicity(std::istream & load, const char* shapeType)
+{
   bool isOK = true;
 
   std::string periodicitySeparator;
@@ -2802,35 +3557,27 @@ void BLSURFPlugin_Hypothesis::LoadPreCADPeriodicity(std::istream & load, const c
 
   while (isOK) {
     isOK = static_cast<bool>(load >> periodicitySeparator); // __BEGIN_PERIODICITY_DESCRIPTION__
-    MESSAGE("periodicitySeparator 1: " <<periodicitySeparator);
     TPreCadPeriodicity *periodicity_i = new TPreCadPeriodicity();
-//     MESSAGE("periodicitySeparator: " <<periodicitySeparator);
     std::string endSeparator = "__PRECAD_" + std::string(shapeType) + "_PERIODICITY_END__";
     if (periodicitySeparator == endSeparator)
       break; // __PRECAD_FACES_PERIODICITY_END__
     if (periodicitySeparator != "__BEGIN_PERIODICITY_DESCRIPTION__"){
-      MESSAGE("//" << endSeparator << "//");
-      MESSAGE("//" << periodicitySeparator << "//");
       throw std::exception();
     }
 
     while (isOK) {
       isOK = static_cast<bool>(load >> periodicitySeparator);
-      MESSAGE("periodicitySeparator 2: " <<periodicitySeparator);
       if (periodicitySeparator == "__END_PERIODICITY_DESCRIPTION__") {
 
         periodicity_i->shape1Entry = shape1Entry;
         periodicity_i->shape2Entry = shape2Entry;
 
-        MESSAGE("theSourceVerticesEntries.size(): " << theSourceVerticesEntries.size());
-        MESSAGE("theTargetVerticesEntries.size(): " << theTargetVerticesEntries.size());
-
         if (hasSourceVertices)
           periodicity_i->theSourceVerticesEntries = theSourceVerticesEntries;
         if (hasTargetVertices)
           periodicity_i->theTargetVerticesEntries = theTargetVerticesEntries;
 
-        if ( shapeType  &&  strcmp( shapeType, "FACES" ))
+        if ( shapeType  &&  strcmp( shapeType, "FACES" ) == 0 )
           _preCadFacesPeriodicityVector.push_back(*periodicity_i);
         else
           _preCadEdgesPeriodicityVector.push_back(*periodicity_i);
@@ -2847,7 +3594,6 @@ void BLSURFPlugin_Hypothesis::LoadPreCADPeriodicity(std::istream & load, const c
         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_ENTRY1__
         if (periodicitySeparator != "__END_ENTRY1__")
           throw std::exception();
-        MESSAGE("shape1Entry: " <<shape1Entry);
       }
 
       if (periodicitySeparator == "__BEGIN_ENTRY2__") {  // __BEGIN_ENTRY2__
@@ -2855,7 +3601,6 @@ void BLSURFPlugin_Hypothesis::LoadPreCADPeriodicity(std::istream & load, const c
         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_ENTRY2__
         if (periodicitySeparator != "__END_ENTRY2__")
           throw std::exception();
-        MESSAGE("shape2Entry: " <<shape2Entry);
       }
 
       if (periodicitySeparator == "__BEGIN_SOURCE_VERTICES_LIST__") {  // __BEGIN_SOURCE_VERTICES_LIST__
@@ -2864,7 +3609,6 @@ void BLSURFPlugin_Hypothesis::LoadPreCADPeriodicity(std::istream & load, const c
           isOK = static_cast<bool>(load >> periodicitySeparator);
           if (periodicitySeparator != "__END_SOURCE_VERTICES_LIST__") {
             theSourceVerticesEntries.push_back(periodicitySeparator);
-            MESSAGE("theSourceVerticesEntries: " <<periodicitySeparator);
           }
         }
       }
@@ -2875,7 +3619,6 @@ void BLSURFPlugin_Hypothesis::LoadPreCADPeriodicity(std::istream & load, const c
           isOK = static_cast<bool>(load >> periodicitySeparator);
           if (periodicitySeparator != "__END_TARGET_VERTICES_LIST__") {
             theTargetVerticesEntries.push_back(periodicitySeparator);
-            MESSAGE("theTargetVerticesEntries: " <<periodicitySeparator);
           }
         }
       }
@@ -2899,7 +3642,8 @@ std::istream & operator >>(std::istream & load, BLSURFPlugin_Hypothesis & hyp) {
  */
 //================================================================================
 
-bool BLSURFPlugin_Hypothesis::SetParametersByMesh(const SMESH_Mesh* theMesh, const TopoDS_Shape& theShape) {
+bool BLSURFPlugin_Hypothesis::SetParametersByMesh(const SMESH_Mesh* /*theMesh*/, const TopoDS_Shape& /*theShape*/)
+{
   return false;
 }
 
@@ -2909,7 +3653,8 @@ bool BLSURFPlugin_Hypothesis::SetParametersByMesh(const SMESH_Mesh* theMesh, con
  */
 //================================================================================
 
-double BLSURFPlugin_Hypothesis::GetDefaultPhySize(double diagonal, double bbSegmentation) {
+double BLSURFPlugin_Hypothesis::GetDefaultPhySize(double diagonal, double bbSegmentation)
+{
   if (bbSegmentation != 0 && diagonal != 0)
     return diagonal / bbSegmentation ;
   return 10;
@@ -2921,7 +3666,8 @@ double BLSURFPlugin_Hypothesis::GetDefaultPhySize(double diagonal, double bbSegm
  */
 //================================================================================
 
-double BLSURFPlugin_Hypothesis::GetDefaultMinSize(double diagonal) {
+double BLSURFPlugin_Hypothesis::GetDefaultMinSize(double diagonal)
+{
   if (diagonal != 0)
     return diagonal / 1000.0 ;
   return undefinedDouble();
@@ -2933,7 +3679,8 @@ double BLSURFPlugin_Hypothesis::GetDefaultMinSize(double diagonal) {
  */
 //================================================================================
 
-double BLSURFPlugin_Hypothesis::GetDefaultMaxSize(double diagonal) {
+double BLSURFPlugin_Hypothesis::GetDefaultMaxSize(double diagonal)
+{
   if (diagonal != 0)
     return diagonal / 5.0 ;
   return undefinedDouble();
@@ -2945,7 +3692,8 @@ double BLSURFPlugin_Hypothesis::GetDefaultMaxSize(double diagonal) {
  */
 //================================================================================
 
-double BLSURFPlugin_Hypothesis::GetDefaultChordalError(double diagonal) {
+double BLSURFPlugin_Hypothesis::GetDefaultChordalError(double diagonal)
+{
   if (diagonal != 0)
     return diagonal;
   return undefinedDouble();
@@ -2957,7 +3705,21 @@ double BLSURFPlugin_Hypothesis::GetDefaultChordalError(double diagonal) {
  */
 //================================================================================
 
-double BLSURFPlugin_Hypothesis::GetDefaultTinyEdgeLength(double diagonal) {
+double BLSURFPlugin_Hypothesis::GetDefaultTinyEdgeLength(double diagonal)
+{
+  if (diagonal != 0)
+    return diagonal * 1e-6 ;
+  return undefinedDouble();
+}
+
+//================================================================================
+/*!
+ * \brief Returns default tiny edge optimisation length given a default value of element length ratio
+ */
+//================================================================================
+
+double BLSURFPlugin_Hypothesis::GetDefaultTinyEdgeOptimisationLength(double diagonal)
+{
   if (diagonal != 0)
     return diagonal * 1e-6 ;
   return undefinedDouble();
@@ -2970,14 +3732,110 @@ double BLSURFPlugin_Hypothesis::GetDefaultTinyEdgeLength(double diagonal) {
  */
 //=============================================================================
 
-bool BLSURFPlugin_Hypothesis::SetParametersByDefaults(const TDefaults& dflts, const SMESH_Mesh* theMesh) {
-  double diagonal = dflts._elemLength*_gen->GetBoundaryBoxSegmentation();
-  _phySize = GetDefaultPhySize(diagonal, _gen->GetBoundaryBoxSegmentation());
-  _minSize = GetDefaultMinSize(diagonal);
-  _maxSize = GetDefaultMaxSize(diagonal);
-  _chordalError = GetDefaultChordalError(diagonal);
-  _tinyEdgeLength = GetDefaultTinyEdgeLength(diagonal);
+bool BLSURFPlugin_Hypothesis::SetParametersByDefaults(const TDefaults&  dflts,
+                                                      const SMESH_Mesh* /*theMesh*/)
+{
+  _phySize = GetDefaultPhySize(dflts._diagonal, _gen->GetBoundaryBoxSegmentation());
+  _minSize = GetDefaultMinSize(dflts._diagonal);
+  _maxSize = GetDefaultMaxSize(dflts._diagonal);
+  _chordalError = 0.5 * _phySize; //GetDefaultChordalError(diagonal); IMP 0023307
+
+  if ( dflts._way == SMESH_Hypothesis::BY_AVERAGE_LENGTH )
+  {
+    _phySize      = dflts._elemLength;
+    _minSize      = dflts._elemLength / 100.;
+    _maxSize      = dflts._elemLength * 2.;
+    _chordalError = dflts._elemLength / 2.;
+    _elementType  = dflts._quadDominated ? QuadrangleDominant : Triangles;
+    _physicalMesh = PhysicalLocalSize; // to activate _enforcedInternalVerticesAllFaces
+    _enforcedInternalVerticesAllFaces = true;
+  }
+  else
+  {
+    _tinyEdgeLength = GetDefaultTinyEdgeLength(dflts._diagonal);
+    _tinyEdgeOptimisationLength = GetDefaultTinyEdgeOptimisationLength(dflts._diagonal);
+  }
 
   return true;
-//   return bool(_phySize = dflts._elemLength);
 }
+
+//================================================================================
+/*!
+ * \brief Converts a string to a bool
+ */
+//================================================================================
+
+bool BLSURFPlugin_Hypothesis::ToBool(const std::string& str, bool* isOk )
+{
+  std::string s = str;
+  if ( isOk ) *isOk = true;
+
+  for ( size_t i = 0; i <= s.size(); ++i )
+    s[i] = (char) tolower( s[i] );
+
+  if ( s == "1" || s == "true" || s == "active" || s == "yes" )
+    return true;
+
+  if ( s == "0" || s == "false" || s == "inactive" || s == "no" )
+    return false;
+
+  if ( isOk )
+    *isOk = false;
+  else {
+    std::string msg = "Not a Boolean value:'" + str + "'";
+    throw std::invalid_argument(msg);
+  }
+  return false;
+}
+
+//================================================================================
+/*!
+ * \brief Converts a string to a real value
+ */
+//================================================================================
+
+double BLSURFPlugin_Hypothesis::ToDbl(const std::string& str, bool* isOk )
+{
+  if ( str.empty() ) throw std::invalid_argument("Empty value provided");
+
+  // Forces "C" locale to be set as LC_NUMERIC
+  Kernel_Utils::Localizer loc;
+
+  char * endPtr;
+  double val = strtod(&str[0], &endPtr);
+  bool ok = (&str[0] != endPtr);
+
+  if ( isOk ) *isOk = ok;
+
+  if ( !ok )
+  {
+    std::string msg = "Not a real value:'" + str + "'";
+    throw std::invalid_argument(msg);
+  }
+  return val;
+}
+
+//================================================================================
+/*!
+ * \brief Converts a string to a integer value
+ */
+//================================================================================
+
+int BLSURFPlugin_Hypothesis::ToInt(const std::string& str, bool* isOk )
+{
+  if ( str.empty() ) throw std::invalid_argument("Empty value provided");
+
+  char * endPtr;
+  int val = (int)strtol( &str[0], &endPtr, 10);
+  bool ok = (&str[0] != endPtr);
+
+  if ( isOk ) *isOk = ok;
+
+  if ( !ok )
+  {
+    std::string msg = "Not an integer value:'" + str + "'";
+    throw std::invalid_argument(msg);
+  }
+  return val;
+}
+