diff --git a/Common/Context.h b/Common/Context.h
index 7ac14b4d99a4fc41096d4ef168fb06075fe02d48..caaa684ef4703581580ac4a965556869f692ed62 100644
--- a/Common/Context.h
+++ b/Common/Context.h
@@ -10,6 +10,7 @@
 #include <string>
 
 #include "CGNSOptions.h"
+#include "PartitionOptions.h"
 
 // Interface-independent context 
 
@@ -172,6 +173,7 @@ class Context_T {
     double angle_smooth_normals;
     double allow_swap_edge_angle;
     int zone_definition;
+    PartitionOptions partition_options;
     CGNSOptions cgns_options;
   } mesh;
 
diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h
index 1c82d209478f32b04deff851500970d556e974df..dc6a5e407db8c74997fe253c8c7b917e67d28c1b 100644
--- a/Common/DefaultOptions.h
+++ b/Common/DefaultOptions.h
@@ -900,6 +900,36 @@ StringXNumber MeshOptions_Number[] = {
 
   { F|O, "C1Continuity" , opt_mesh_c1 , 0. ,
     "Impose C1 continuity to high order meshes (only valid in 2D plane and ElemenOrder = 2)" },
+  { F|O, "ChacoArchitecture" , opt_mesh_partition_chaco_architecture, 1. ,
+    "(Adv. Chaco): Parallel architecture topology (0=hypercube, 1-3=mesh dimensions)" },
+  { F|O, "ChacoEigensolver" , opt_mesh_partition_chaco_eigensolver, 1. ,
+    "(Adv. Chaco): Type of eigensolver for a spectral algorithm (0=Lanczos, 1=Multilevel RQI/Symmlq)" },
+  { F|O, "ChacoEigTol" , opt_mesh_partition_chaco_eigtol, 1.E-3 ,
+    "(Adv. Chaco): Tolerance of the eigensolver for spectral or multilevel-KL algorithms" },
+  { F|O, "ChacoHypercubeDim" , opt_mesh_partition_chaco_ndims_tot, 2. ,
+    "(Adv. Chaco): Dimensional partitioning for a hypercube topology" },
+  { F|O, "ChacoLocalMethod" , opt_mesh_partition_chaco_local_method, 1. ,
+    "(Adv. Chaco): Local partitioning algorithm" },
+  { F|O, "ChacoMeshDim1" , opt_mesh_partition_chaco_mesh_dims1, 4. ,
+    "(Adv. Chaco): Number of partitions in the first dimension of a mesh topology" },
+  { F|O, "ChacoMeshDim2" , opt_mesh_partition_chaco_mesh_dims2, 1. ,
+    "(Adv. Chaco): Number of partitions in the second dimension of a mesh topology" },
+  { F|O, "ChacoMeshDim3" , opt_mesh_partition_chaco_mesh_dims3, 1. ,
+    "(Adv. Chaco): Number of partitions in the third dimension of a mesh topology" },
+  { F|O, "ChacoPartitionSection" , opt_mesh_partition_chaco_nsection, 1. ,
+    "(Adv. Chaco): Partition by (1=bisection, 2=quadrisection, 3=octasection" },
+  { F|O, "ChacoSeed" , opt_mesh_partition_chaco_seed, 7654321. ,
+    "(Adv. Chaco): Seed for random number generator" },
+  { F|O, "ChacoVMax" , opt_mesh_partition_chaco_vmax, 250. ,
+    "(Adv. Chaco): Maximum vertices in a coarse graph (for multilevel-KL algorithm and Multilevel RQI/Symmlq eigensolver)" },
+  { F|O, "ChacoParamINTERNAL_VERTICES" , opt_mesh_partition_chaco_internal_vertices, 1. ,
+    "(Adv. Chaco): Parameter INTERNAL_VERTICES" },
+  { F|O, "ChacoParamREFINE_MAP" , opt_mesh_partition_chaco_refine_map, 1. ,
+    "(Adv. Chaco): Parameter REFINE_MAP" },
+  { F|O, "ChacoParamREFINE_PARTITION" , opt_mesh_partition_chaco_refine_partition, 0. ,
+    "(Adv. Chaco): Parameter REFINE_PARTITION" },
+  { F|O, "ChacoParamTERMINAL_PROPOGATION" , opt_mesh_partition_chaco_terminal_propogation, 1. ,
+    "(Adv. Chaco): Parameter TERMINAL_PROPOGATION" },
   { F|O, "CharacteristicLengthExtendFromBoundary" , opt_mesh_lc_extend_from_boundary, 1. ,
     "Extend characteristic lengths from the boundaries inside the surface/volume" },
   { F|O, "CharacteristicLengthFactor" , opt_mesh_lc_factor , 1.0 ,
@@ -950,6 +980,10 @@ StringXNumber MeshOptions_Number[] = {
   { F|O, "LineWidth" , opt_mesh_line_width , 1.0 , 
     "Display width of mesh lines (in pixels)" },
 
+  { F|O, "MetisEdgeMatching" , opt_mesh_partition_metis_edge_matching, 3. ,
+    "(Adv. METIS): Determines the matching type (1=Random, 2=Heavy-Edge, 3=Sorted Heavy-Edge)" },
+  { F|O, "MetisRefinementAlgorithm" , opt_mesh_partition_metis_refine_algorithm, 3. ,
+    "(Adv. METIS): Algorithm for k-way refinement (1=Random, 2=Greedy, 3=Random with minimized connectivity)" },
   { F|O, "MinimumCirclePoints" , opt_mesh_min_circ_points, 7. ,
     "Minimum number of points used to mesh a circle" },
   { F|O, "MinimumCurvePoints" , opt_mesh_min_curv_points, 3. ,
@@ -963,6 +997,8 @@ StringXNumber MeshOptions_Number[] = {
     "Number of hexahedra in the current mesh (read-only)" },
   { F, "NbNodes" , opt_mesh_nb_nodes , 0. , 
     "Number of nodes in the current mesh (read-only)" },
+  { F|O, "NbPartitions" , opt_mesh_partition_num, 4. ,
+    "Number of partitions" },
   { F, "NbPrisms" , opt_mesh_nb_prisms , 0. , 
     "Number of prisms in the current mesh (read-only)" },
   { F, "NbPyramids" , opt_mesh_nb_pyramids , 0. , 
@@ -981,6 +1017,10 @@ StringXNumber MeshOptions_Number[] = {
   { F|O, "OptimizeNetgen" , opt_mesh_optimize_netgen , 0. , 
     "Optimize the mesh using Netgen to improve the quality of tetrahedral elements" },
 
+  { F|O, "Partitioner" , opt_mesh_partition_partitioner, 1. ,
+    "Partitioner software (1=Chacho, 2=METIS)" },
+  { F|O, "PartitionerAlgorithm" , opt_mesh_partition_algorithm, 1. ,
+    "Partitioning algorithm (Chaco: 1=Multilevel-KL, 2=Spectral, 4=Linear, 5=Random, 6=Scattered; METIS: 1=Recursive, 2=K-way)" },
   { F|O, "Points" , opt_mesh_points , 0. , 
     "Display mesh vertices (nodes)?" },
   { F|O, "PointNumbers" , opt_mesh_points_num , 0. , 
diff --git a/Common/Options.cpp b/Common/Options.cpp
index cb813691748a496cad5ab11f8b8bc5d47b7d6f6f..cfa316a1511df383269df03763ee57f61e10ede2 100644
--- a/Common/Options.cpp
+++ b/Common/Options.cpp
@@ -5298,6 +5298,219 @@ double opt_mesh_cpu_time(OPT_ARGS_NUM)
   return s[13] + s[14] + s[15];
 }
 
+double opt_mesh_partition_partitioner(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET) {
+    const int ival = (int)val;
+    CTX.mesh.partition_options.partitioner = (ival < 1 || ival > 2) ? 1 : ival;
+  }
+  return CTX.mesh.partition_options.partitioner;
+}
+
+double opt_mesh_partition_num(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET) {
+    const int ival = std::max(1, (int)val);
+    CTX.mesh.partition_options.num_partitions = ival;
+    unsigned hcdim = 0;  // log2 to get hypercube dimensions
+    unsigned jval = ival;
+    while(jval >>= 1) ++hcdim;
+    CTX.mesh.partition_options.ndims_tot = hcdim;
+    CTX.mesh.partition_options.mesh_dims[0] = ival;
+    CTX.mesh.partition_options.mesh_dims[1] = 1;
+    CTX.mesh.partition_options.mesh_dims[2] = 1;
+    if(CTX.mesh.partition_options.partitioner == 2)  // METIS
+       CTX.mesh.partition_options.algorithm = (ival <= 8) ? 1 : 2;
+  }
+  return CTX.mesh.partition_options.num_partitions;
+}
+
+double opt_mesh_partition_algorithm(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET) {
+    int ival = (int)val;
+    switch(CTX.mesh.partition_options.partitioner) {
+    case 1:
+      if(ival < 1 || ival > 6 || ival == 3) ival = 1;
+      break;
+    case 2:
+      if(ival < 1 || ival > 2)
+        ival = (CTX.mesh.partition_options.num_partitions <= 8) ? 1 : 2;
+      break;
+    }
+    CTX.mesh.partition_options.algorithm = ival;
+  }
+  return  CTX.mesh.partition_options.algorithm;
+}
+
+double opt_mesh_partition_chaco_architecture(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET) {
+    const int ival = (int)val;
+    CTX.mesh.partition_options.architecture =
+      (ival < 0 || ival > 3) ? 1 : ival;
+  }
+  return CTX.mesh.partition_options.architecture;
+}
+
+double opt_mesh_partition_chaco_ndims_tot(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET) {
+    const int ival = std::max(1, (int)val);
+    CTX.mesh.partition_options.ndims_tot = ival;
+    CTX.mesh.partition_options.num_partitions = 1 << ival;
+  }
+  return CTX.mesh.partition_options.ndims_tot;
+}
+
+double opt_mesh_partition_chaco_mesh_dims1(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET) {
+    const int ival = std::max(1, (int)val);
+    CTX.mesh.partition_options.mesh_dims[0] = ival;
+    CTX.mesh.partition_options.num_partitions = ival;
+    if(CTX.mesh.partition_options.architecture >= 2)
+      CTX.mesh.partition_options.num_partitions *=
+        CTX.mesh.partition_options.mesh_dims[1];
+    if(CTX.mesh.partition_options.architecture == 3)
+      CTX.mesh.partition_options.num_partitions *=
+        CTX.mesh.partition_options.mesh_dims[2];
+  }
+  return CTX.mesh.partition_options.mesh_dims[0];
+}
+
+double opt_mesh_partition_chaco_mesh_dims2(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET) {
+    const int ival = std::max(1, (int)val);
+    CTX.mesh.partition_options.mesh_dims[1] = ival;
+    CTX.mesh.partition_options.num_partitions =
+      CTX.mesh.partition_options.mesh_dims[0]*ival;
+    if(CTX.mesh.partition_options.architecture == 3)
+      CTX.mesh.partition_options.num_partitions *=
+        CTX.mesh.partition_options.mesh_dims[2];
+  }
+  return CTX.mesh.partition_options.mesh_dims[1];
+}
+
+double opt_mesh_partition_chaco_mesh_dims3(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET) {
+    const int ival = std::max(1, (int)val);
+    CTX.mesh.partition_options.mesh_dims[2] = ival;
+    CTX.mesh.partition_options.num_partitions =
+      CTX.mesh.partition_options.mesh_dims[0]*
+      CTX.mesh.partition_options.mesh_dims[1]*ival;
+  }
+  return CTX.mesh.partition_options.mesh_dims[2];
+}
+
+double opt_mesh_partition_chaco_local_method(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET) {
+    int ival = (int)val;
+    if(CTX.mesh.partition_options.algorithm == 1) ival = 1;
+    CTX.mesh.partition_options.local_method = (ival < 0 || ival > 1) ? 1 : ival;
+  }
+  return CTX.mesh.partition_options.local_method;
+}
+
+double opt_mesh_partition_chaco_eigensolver(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET) {
+    int ival = val ? 1 : 0;
+    CTX.mesh.partition_options.rqi_flag = ival;
+  }
+  return CTX.mesh.partition_options.rqi_flag;
+}
+
+double opt_mesh_partition_chaco_vmax(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET) {
+    const int ival = (int)val;
+    CTX.mesh.partition_options.vmax = (ival < 1) ? 1 : ival;
+  }
+  return CTX.mesh.partition_options.vmax;
+}
+
+double opt_mesh_partition_chaco_nsection(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET) {
+    const int ival = (int)val;
+    CTX.mesh.partition_options.ndims = (ival < 1 || ival > 3) ? 1 : ival;
+    if(CTX.mesh.partition_options.ndims > 1 &&
+       CTX.mesh.partition_options.algorithm == 2)
+      CTX.mesh.partition_options.terminal_propogation = false;
+  }
+  return CTX.mesh.partition_options.ndims;
+}
+
+double opt_mesh_partition_chaco_eigtol(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET)
+    CTX.mesh.partition_options.eigtol = (val <= 0.) ? 1.E-3 : val;
+  return CTX.mesh.partition_options.eigtol;
+}
+
+double opt_mesh_partition_chaco_seed(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET)
+    CTX.mesh.partition_options.seed = (long)val;
+  return CTX.mesh.partition_options.seed;
+}
+
+double opt_mesh_partition_chaco_refine_partition(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET)
+    CTX.mesh.partition_options.refine_partition = val ? 1 : 0;
+  return CTX.mesh.partition_options.refine_partition;
+}
+
+double opt_mesh_partition_chaco_internal_vertices(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET)
+    CTX.mesh.partition_options.internal_vertices = val ? 1 : 0;
+  return CTX.mesh.partition_options.internal_vertices;
+}
+
+double opt_mesh_partition_chaco_refine_map(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET)
+    CTX.mesh.partition_options.refine_map = val ? 1 : 0;
+  return CTX.mesh.partition_options.refine_map;
+}
+
+double opt_mesh_partition_chaco_terminal_propogation(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET) {
+    CTX.mesh.partition_options.terminal_propogation = val ? 1 : 0;
+    if(CTX.mesh.partition_options.terminal_propogation &&
+       CTX.mesh.partition_options.algorithm == 2)
+      CTX.mesh.partition_options.ndims = 1;
+  }
+  return CTX.mesh.partition_options.terminal_propogation;
+}
+
+double opt_mesh_partition_metis_edge_matching(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET) {
+    const int ival = (int)val;
+    CTX.mesh.partition_options.edge_matching =
+      (ival < 1 || ival > 3) ? 3 : ival;
+  }
+  return CTX.mesh.partition_options.edge_matching;
+}
+
+double opt_mesh_partition_metis_refine_algorithm(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET) {
+    const int ival = (int)val;
+    CTX.mesh.partition_options.refine_algorithm =
+      (ival < 1 || ival > 3) ? 3 : ival;
+  }
+  return CTX.mesh.partition_options.refine_algorithm;
+}
+
 double opt_solver_max_delay(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
diff --git a/Common/Options.h b/Common/Options.h
index 82a114d7d49cfc4ceae6d09683146bef0ded78fb..41f265c49ee1f053f941aa0d48561a23686b901a 100644
--- a/Common/Options.h
+++ b/Common/Options.h
@@ -498,6 +498,26 @@ double opt_mesh_nb_hexahedra(OPT_ARGS_NUM);
 double opt_mesh_nb_prisms(OPT_ARGS_NUM);
 double opt_mesh_nb_pyramids(OPT_ARGS_NUM);
 double opt_mesh_cpu_time(OPT_ARGS_NUM);
+double opt_mesh_partition_partitioner(OPT_ARGS_NUM);
+double opt_mesh_partition_num(OPT_ARGS_NUM);
+double opt_mesh_partition_algorithm(OPT_ARGS_NUM);
+double opt_mesh_partition_chaco_architecture(OPT_ARGS_NUM);
+double opt_mesh_partition_chaco_ndims_tot(OPT_ARGS_NUM);
+double opt_mesh_partition_chaco_mesh_dims1(OPT_ARGS_NUM);
+double opt_mesh_partition_chaco_mesh_dims2(OPT_ARGS_NUM);
+double opt_mesh_partition_chaco_mesh_dims3(OPT_ARGS_NUM);
+double opt_mesh_partition_chaco_local_method(OPT_ARGS_NUM);
+double opt_mesh_partition_chaco_eigensolver(OPT_ARGS_NUM);
+double opt_mesh_partition_chaco_vmax(OPT_ARGS_NUM);
+double opt_mesh_partition_chaco_nsection(OPT_ARGS_NUM);
+double opt_mesh_partition_chaco_eigtol(OPT_ARGS_NUM);
+double opt_mesh_partition_chaco_seed(OPT_ARGS_NUM);
+double opt_mesh_partition_chaco_refine_partition(OPT_ARGS_NUM);
+double opt_mesh_partition_chaco_internal_vertices(OPT_ARGS_NUM);
+double opt_mesh_partition_chaco_refine_map(OPT_ARGS_NUM);
+double opt_mesh_partition_chaco_terminal_propogation(OPT_ARGS_NUM);
+double opt_mesh_partition_metis_edge_matching(OPT_ARGS_NUM);
+double opt_mesh_partition_metis_refine_algorithm(OPT_ARGS_NUM);
 double opt_solver_max_delay(OPT_ARGS_NUM);
 double opt_solver_listen(OPT_ARGS_NUM);
 double opt_solver_plugins(OPT_ARGS_NUM);
diff --git a/Fltk/Callbacks.cpp b/Fltk/Callbacks.cpp
index a74a778ff7c77b28e86163e612dc9bce362b2639..614ac299b14b336f1f2c4d53bb0f024732a04116 100644
--- a/Fltk/Callbacks.cpp
+++ b/Fltk/Callbacks.cpp
@@ -3741,6 +3741,14 @@ void mesh_optimize_netgen_cb(CALLBACK_ARGS)
   Msg::StatusBar(2, false, " ");
 }
 
+void mesh_partition_cb(CALLBACK_ARGS)
+{
+  partition_dialog();
+  CTX.mesh.changed |= (ENT_LINE | ENT_SURFACE | ENT_VOLUME);
+  Draw();
+  Msg::StatusBar(2, false, " ");
+}
+
 void mesh_define_length_cb(CALLBACK_ARGS)
 {
   _action_point_line_surface_volume(8, 0, "Point");
diff --git a/Fltk/Callbacks.h b/Fltk/Callbacks.h
index d7c41dbe77590ef33a07e92f1d5450cd0e36a52b..85588ed8cc82574842ee784064b96f3f46cadf14 100644
--- a/Fltk/Callbacks.h
+++ b/Fltk/Callbacks.h
@@ -233,6 +233,7 @@ void mesh_parameterize_cb(CALLBACK_ARGS);
 void mesh_degree_cb(CALLBACK_ARGS); 
 void mesh_optimize_cb(CALLBACK_ARGS); 
 void mesh_optimize_netgen_cb(CALLBACK_ARGS); 
+void mesh_partition_cb(CALLBACK_ARGS);
 void mesh_classify_cb(CALLBACK_ARGS); 
 void mesh_define_length_cb (CALLBACK_ARGS);
 void mesh_define_recombine_cb (CALLBACK_ARGS);
diff --git a/Fltk/GUI.cpp b/Fltk/GUI.cpp
index 5030cf958bded4f682d4a96643997a45c86ea5fb..3a14c9d43805b4f635f0083b1a986b90d8311a39 100644
--- a/Fltk/GUI.cpp
+++ b/Fltk/GUI.cpp
@@ -300,6 +300,9 @@ Context_Item menu_mesh[] = {
 #if defined(HAVE_NETGEN)
   {"Optimize (Netgen)", (Fl_Callback *)mesh_optimize_netgen_cb} , 
 #endif
+#if defined(HAVE_METIS)
+  {"Partition", (Fl_Callback *)mesh_partition_cb} ,
+#endif
 #if defined(HAVE_FOURIER_MODEL)
   {"Reparameterize",   (Fl_Callback *)mesh_parameterize_cb} , 
 #endif
diff --git a/Fltk/GUI_Extras.cpp b/Fltk/GUI_Extras.cpp
index 64ba77cc54bfbb92b6a494e30c50f4a2a10eb898..7523a11d89be3f5d54a5c600224c2f27eb2071c5 100644
--- a/Fltk/GUI_Extras.cpp
+++ b/Fltk/GUI_Extras.cpp
@@ -3,6 +3,8 @@
 // See the LICENSE.txt file for license information. Please report all
 // bugs and problems to <gmsh@geuz.org>.
 
+#include <limits>
+
 #include "GmshUI.h"
 #include "GmshDefines.h"
 #include "CreateFile.h"
@@ -16,6 +18,7 @@
 #include <FL/Fl_Value_Slider.H>
 #include <FL/Fl_Menu_Window.H>
 #include <FL/Fl_Select_Browser.H>
+#include <FL/Fl_Toggle_Button.H>
 #include <errno.h>
 
 #if defined(HAVE_NATIVE_FILE_CHOOSER)
@@ -1133,3 +1136,575 @@ int stl_dialog(const char *name)
   }
   return 0;
 }
+
+// Partition dialog
+
+struct PartitionDialog 
+{
+  Fl_Choice *choicePartitioner;
+  Fl_Choice *choiceChacoAlg;
+  Fl_Choice *choiceMetisAlg;
+  Fl_Toggle_Button *toggleButtonAdvChaco;
+  Fl_Toggle_Button *toggleButtonAdvMetis;
+  Fl_Choice *choiceArchitecture;
+  Fl_Value_Input *inputNumPartition;
+  Fl_Value_Input *inputNumPartition1;
+  Fl_Value_Input *inputNumPartition2;
+  Fl_Value_Input *inputNumPartition3;
+  Fl_Choice *choiceDivisions;
+  Fl_Choice *choiceEigensolver;
+  Fl_Choice *choiceLocalAlgorithm;
+  Fl_Check_Button *checkButtonTermProp;
+};
+
+inline void partition_opt_chaco_globalalg_cb(Fl_Widget *widget, void *data)
+{
+  PartitionDialog *dlg = static_cast<PartitionDialog*>(data);
+  unsigned opt = dlg->choiceChacoAlg->value();
+  if(opt == 0) {
+    dlg->choiceLocalAlgorithm->value(0);
+    dlg->choiceLocalAlgorithm->deactivate();
+  }
+  else {
+    dlg->choiceLocalAlgorithm->activate();
+  }
+  if(opt == 1) {
+    dlg->choiceEigensolver->activate();
+    if(dlg->choiceDivisions->value() != 0 &&
+       dlg->checkButtonTermProp->value())
+      dlg->choiceDivisions->value(0);
+  }
+  else {
+    dlg->choiceEigensolver->deactivate();
+  }
+}
+
+inline void partition_opt_architecture_cb(Fl_Widget *widget, void *data)
+{
+  PartitionDialog *dlg = static_cast<PartitionDialog*>(data);
+  switch(static_cast<int>(dlg->choiceArchitecture->value())) {
+  case 0:
+    dlg->inputNumPartition1->maximum(31);
+    dlg->inputNumPartition2->deactivate();
+    dlg->inputNumPartition3->deactivate();
+    break;
+  case 1:
+    dlg->inputNumPartition1->maximum(std::numeric_limits<int>::max());
+    dlg->inputNumPartition2->deactivate();
+    dlg->inputNumPartition3->deactivate();
+    break;
+  case 2:
+    dlg->inputNumPartition1->maximum(std::numeric_limits<int>::max());
+    dlg->inputNumPartition2->activate();
+    dlg->inputNumPartition3->deactivate();
+    break;
+  case 3:
+    dlg->inputNumPartition1->maximum(std::numeric_limits<int>::max());
+    dlg->inputNumPartition2->activate();
+    dlg->inputNumPartition3->activate();
+    break;
+  }
+}
+
+inline void partition_opt_num_partitions_cb(Fl_Widget *widget, void *data)
+{
+  PartitionDialog *dlg = static_cast<PartitionDialog*>(data);
+  unsigned val;
+  if(widget == dlg->inputNumPartition) {
+    val = dlg->inputNumPartition->value();
+    switch(static_cast<int>(dlg->choiceArchitecture->value())) {
+    case 0:
+      {
+        unsigned y = 0;
+        unsigned x = val;
+        while(x >>= 1) ++y;
+        dlg->inputNumPartition1->value(y);
+      }
+      break;
+    case 1:
+    case 2:
+    case 3:
+      dlg->inputNumPartition1->value(val);
+      dlg->inputNumPartition2->value(1);
+      dlg->inputNumPartition3->value(1);
+      break;
+    }
+  }
+  else {
+    switch(static_cast<int>(dlg->choiceArchitecture->value())) {
+    case 0:
+      {
+        unsigned x = dlg->inputNumPartition1->value();
+        val = 1 << x;
+      }
+      break;
+    case 1:
+      val = dlg->inputNumPartition1->value();
+      break;
+    case 2:
+      val = dlg->inputNumPartition1->value()*dlg->inputNumPartition2->value();
+      break;
+    case 3:
+      val = dlg->inputNumPartition1->value()*dlg->inputNumPartition2->value()*
+        dlg->inputNumPartition3->value();
+      break;
+    }
+    dlg->inputNumPartition->value(val);
+  }
+  if(dlg->choicePartitioner->value() == 1) {
+    dlg->choiceMetisAlg->value((val <= 8) ? 0: 1);
+  }
+}
+
+inline void partition_opt_spectralcheck_cb(Fl_Widget *widget, void *data)
+{
+  PartitionDialog *dlg = static_cast<PartitionDialog*>(data);
+  if(dlg->choiceChacoAlg->value() == 1) {
+    if(widget == dlg->choiceDivisions && dlg->choiceDivisions->value() != 0)
+      dlg->checkButtonTermProp->value(0);
+    else if(widget == dlg->checkButtonTermProp)
+      dlg->choiceDivisions->value(0);
+  }
+}
+
+inline void partition_partition_cb(Fl_Widget *widget, void *data)
+{
+  Fl::delete_widget(widget->window());
+}
+inline void partition_cancel_cb(Fl_Widget *widget, void *data)
+{
+  Fl::delete_widget(widget->window());
+}
+inline void partition_select_groups_cb(Fl_Widget *widget, void *data)
+{
+  PartitionDialog *dlg = static_cast<PartitionDialog*>(data);
+  const int WB = 7;                     // Window border
+  Fl_Window *const w = widget->window();
+  // Get the groups
+  Fl_Widget *const *g = w->array();
+  int y = g[0]->h();
+  switch(dlg->choicePartitioner->value()) {
+  case 0:
+    g[1]->show();
+    y += g[1]->h();
+    if(dlg->toggleButtonAdvChaco->value()) {
+      g[2]->show();
+      y += g[2]->h();
+    }
+    else g[2]->hide();
+    g[3]->hide();
+    g[4]->hide();
+    break;
+  case 1:
+    g[3]->show();
+    y += g[3]->h();
+    if(dlg->toggleButtonAdvMetis->value()) {
+      g[4]->show();
+      y += g[4]->h();
+    }
+    else g[4]->hide();
+    g[1]->hide();
+    g[2]->hide();
+    break;
+  }
+  // Reset the vertical position of all widgets in group 6
+  {
+    int yG = y;
+    g[5]->position(g[5]->x(), yG);
+    Fl_Widget *o = static_cast<Fl_Group*>(g[5])->child(0);
+    o->position(o->x(), yG);
+    yG += WB + o->h();
+    o = static_cast<Fl_Group*>(g[5])->child(1);
+    o->position(o->x(), yG);
+    o = static_cast<Fl_Group*>(g[5])->child(2);
+    o->position(o->x(), yG);
+    yG += WB + o->h();
+  }
+  y += g[5]->h();
+  // Resize and redraw the window
+  w->size(w->w(), y);
+  w->redraw();
+}
+
+int partition_dialog()
+{
+  static PartitionDialog dlg;
+
+  static Fl_Menu_Item partitionTypeMenu[] = {
+    {"Chaco", 0, 0, 0},
+    {"Metis", 0, 0, 0},
+    {0}
+  };
+
+  static Fl_Menu_Item chacoAlgMenu[] = {
+    {"Multilevel-KL", 0, 0, 0},
+    {"Spectral", 0, 0, 0},
+    {"Inertial", 0, 0, 0, FL_MENU_INACTIVE},
+    {"Linear", 0, 0, 0},
+    {"Random", 0, 0, 0},
+    {"Scattered", 0, 0, 0},
+    {0}
+  };
+
+  static Fl_Menu_Item metisAlgMenu[] = {
+    {"Recursive", 0, 0, 0},
+    {"K-way", 0, 0, 0},
+    {0}
+  };
+
+  static Fl_Menu_Item chachoArchitectureMenu[] = {
+    {"Hypercube", 0, 0, 0},
+    {"1-D Mesh", 0, 0, 0},
+    {"2-D Mesh", 0, 0, 0},
+    {"3-D Mesh", 0, 0, 0},
+    {0}
+  };
+
+  static Fl_Menu_Item chachoLocalMethodMenu[] = {
+    {"Kernighan-Lin", 0, 0, 0},
+    {"None", 0, 0, 0},
+    {0}
+  };
+
+  static Fl_Menu_Item chachoEigSolMenu[] = {
+    {"Lanczos", 0, 0, 0},
+    {"Multilevel RQI/Symmlq", 0, 0, 0},
+    {0}
+  };
+
+  static Fl_Menu_Item chachoDivisionsMenu[] = {
+    {"Bisection", 0, 0, 0},
+    {"Quadrisection", 0, 0, 0},
+    {"Octasection", 0, 0, 0},
+    {0}
+  };
+
+  static Fl_Menu_Item metisEdgeMatchingMenu[] = {
+    {"Random", 0, 0, 0},
+    {"Heavy-edge", 0, 0, 0},
+    {"Sorted heavy-edge", 0, 0, 0},
+    {0}
+  };
+
+  static Fl_Menu_Item metisRefineAlgMenu[] = {
+    {"Random", 0, 0, 0},
+    {"Greedy", 0, 0, 0},
+    {"Random (Min. Conn.)", 0, 0, 0},
+    {0}
+  };
+
+  const int IW = 10*GetFontSize();      // Input field width
+  const int BH = 2*GetFontSize() + 1;   // button height
+  const int BB = 7*GetFontSize() + 9;   // Width of a button with an internal
+                                        // label
+  const int WB = 7;                     // Window border
+
+  const int h = 3 * WB + 3 * BH;
+  const int w = 3 * BB + IW + 3 * WB;
+  int y = 0;
+
+  Fl_Double_Window *const window =
+    new Fl_Double_Window(w, h, "Partitioner Options");
+  window->box(GMSH_WINDOW_BOX);
+
+  // Main options group [0]
+  {
+    const int GH = BH + 2 + 3*WB;
+    y += WB;
+    Fl_Group *g = new Fl_Group(0, y, w, GH);
+    // Partitioner
+    {
+      Fl_Choice *const o = new Fl_Choice(WB, y, BB, BH, "Partitioner");
+      dlg.choicePartitioner = o;
+      o->menu(partitionTypeMenu);
+      o->value(CTX.mesh.partition_options.partitioner - 1);
+      o->callback((Fl_Callback *)partition_select_groups_cb, &dlg);
+      o->align(FL_ALIGN_RIGHT);
+    }
+    // Number of partitions
+    {
+      Fl_Value_Input *const o = new Fl_Value_Input
+        (2*WB + 2*BB, y, IW, BH, "Number of\nPartitions");
+      dlg.inputNumPartition = o;
+      o->minimum(1);
+      o->maximum(std::numeric_limits<int>::max());
+      o->value(CTX.mesh.partition_options.num_partitions);
+      o->callback((Fl_Callback *)partition_opt_num_partitions_cb, &dlg);
+      o->step(1);
+      o->align(FL_ALIGN_RIGHT);
+    }
+    y += BH + WB;
+    // Box (line)
+    { Fl_Box* o = new Fl_Box(WB, y, w - 2*WB, 2);
+      o->box(FL_ENGRAVED_FRAME);
+      o->labeltype(FL_NO_LABEL);
+    }
+    y += 2 + WB;
+    g->end();
+    g->show();
+  }
+  const int yMain = y;
+
+  // Chaco options group [1]
+  {
+    const int GH = BH + WB;
+    Fl_Group *g = new Fl_Group(0, y, w, GH);
+    // Algorithm
+    {
+      Fl_Choice *const o = new Fl_Choice(WB, y, IW, BH, "Global Algorithm");
+      dlg.choiceChacoAlg = o;
+      o->menu(chacoAlgMenu);
+      o->value(CTX.mesh.partition_options.algorithm - 1);
+      o->callback((Fl_Callback *)partition_opt_chaco_globalalg_cb, &dlg);
+      o->align(FL_ALIGN_RIGHT);
+    }
+    // Advanced Button
+    {
+      Fl_Toggle_Button *const o = new Fl_Toggle_Button
+        (w - (WB + BB), y, BB, BH, "Advanced @-22->");
+      dlg.toggleButtonAdvChaco = o;
+      o->callback((Fl_Callback *)partition_select_groups_cb, &dlg);
+    }
+    y += BH + WB;
+    g->end();
+    g->hide();
+  }
+
+  // Chaco advanced options group [2]
+  {
+    const int GH = 2 + WB + 5*(BH + WB) + BH + 6;
+    Fl_Group *g = new Fl_Group(0, y, w, GH);
+    // Box (line)
+    {
+      Fl_Box *const o = new Fl_Box(WB, y, w - 2*WB, 2);
+      o->box(FL_ENGRAVED_FRAME);
+      o->labeltype(FL_NO_LABEL);
+    }
+    y += 2 + WB + 1;  // +1 for multiline label
+    {
+      Fl_Choice *const o = new Fl_Choice(WB, y, BB, BH, "Architecture");
+      dlg.choiceArchitecture = o;
+      o->menu(chachoArchitectureMenu);
+      o->value(CTX.mesh.partition_options.architecture);
+      o->callback((Fl_Callback *)partition_opt_architecture_cb, &dlg);
+      o->align(FL_ALIGN_RIGHT);
+    }
+    {
+      Fl_Value_Input *const o = new Fl_Value_Input
+        (2*WB + 2*BB, y, IW/3, BH);
+      dlg.inputNumPartition1 = o;
+      o->minimum(1);
+      o->maximum(std::numeric_limits<int>::max());
+      switch(CTX.mesh.partition_options.architecture) {
+      case 0:
+         o->value(CTX.mesh.partition_options.ndims_tot);
+         break;
+      case 1:
+         o->value(CTX.mesh.partition_options.mesh_dims[0]);
+         break;
+      }
+      o->callback((Fl_Callback *)partition_opt_num_partitions_cb, &dlg);
+      o->step(1);
+    }
+    {
+      Fl_Value_Input *const o = new Fl_Value_Input
+        (2*WB + 2*BB + IW/3, y, IW/3, BH);
+      dlg.inputNumPartition2 = o;
+      o->minimum(1);
+      o->maximum(std::numeric_limits<int>::max());
+      o->value(CTX.mesh.partition_options.mesh_dims[1]);
+      o->callback((Fl_Callback *)partition_opt_num_partitions_cb, &dlg);
+      o->step(1);
+      if(CTX.mesh.partition_options.architecture < 2) o->deactivate();
+    }
+    {
+      Fl_Value_Input *const o = new Fl_Value_Input
+        (2*WB + 2*BB + 2*IW/3, y, IW/3, BH);
+      dlg.inputNumPartition3 = o;
+      o->minimum(1);
+      o->maximum(std::numeric_limits<int>::max());
+      o->value(CTX.mesh.partition_options.mesh_dims[2]);
+      o->callback((Fl_Callback *)partition_opt_num_partitions_cb, &dlg);
+      o->step(1);
+      if(CTX.mesh.partition_options.architecture < 3) o->deactivate();
+    }
+    {
+      Fl_Box *const o = new Fl_Box(2*WB + 2*BB + IW, y, 0, BH,
+                                   "Topology\ndimensions");
+      o->align(FL_ALIGN_RIGHT);
+    }
+    y += BH + WB + 2;  // +2 for multiline labels
+    {
+      Fl_Choice *const o = new Fl_Choice(WB, y, BB, BH, "Divisions");
+      dlg.choiceDivisions = o;
+      o->menu(chachoDivisionsMenu);
+      o->value(CTX.mesh.partition_options.ndims - 1);
+      o->callback((Fl_Callback *)partition_opt_spectralcheck_cb, &dlg);
+      o->align(FL_ALIGN_RIGHT);
+    }
+    {
+      Fl_Value_Input *const o = new Fl_Value_Input
+        (2*WB + 2*BB, y, IW, BH, "Max. vertices in\ncoarse graph");
+      o->minimum(2);
+      o->maximum(std::numeric_limits<double>::max());
+      o->value(CTX.mesh.partition_options.vmax);
+      o->step(1);
+      o->align(FL_ALIGN_RIGHT);
+    }
+    y += BH + WB + 2;  // +2 for multiline labels
+    {
+      Fl_Choice *const o = new Fl_Choice(WB, y, BB, BH, "Eigensolver");
+      dlg.choiceEigensolver = o;
+      o->menu(chachoEigSolMenu);
+      o->value(CTX.mesh.partition_options.rqi_flag);
+      if(CTX.mesh.partition_options.algorithm != 2) o->deactivate();
+      o->align(FL_ALIGN_RIGHT);
+    }
+    {
+      Fl_Value_Input *const o = new Fl_Value_Input
+        (2*WB + 2*BB, y, IW, BH, "Eigensolver\ntolerance");
+      o->minimum(std::numeric_limits<double>::min());
+      o->maximum(std::numeric_limits<double>::max());
+      o->value(CTX.mesh.partition_options.eigtol);
+      o->step(5.E-3);
+      o->align(FL_ALIGN_RIGHT);
+    }
+    y += BH + WB + 1;  // +1 for multiline label
+    {
+      Fl_Choice *const o = new Fl_Choice(WB, y, BB, BH, "Local algorithm");
+      dlg.choiceLocalAlgorithm = o;
+      o->menu(chachoLocalMethodMenu);
+      o->value(CTX.mesh.partition_options.local_method + 1);
+      if(CTX.mesh.partition_options.algorithm == 1) o->deactivate();
+      o->align(FL_ALIGN_RIGHT);
+    }
+    {
+      Fl_Value_Input *const o = new Fl_Value_Input
+        (2*WB + 2*BB, y, IW, BH, "Seed");
+      o->minimum(1);
+      o->maximum(std::numeric_limits<int>::max());
+      o->value(CTX.mesh.partition_options.seed);
+      o->step(1);
+      o->align(FL_ALIGN_RIGHT);
+    }
+    y += BH + WB;
+    {
+      Fl_Check_Button *const o = new Fl_Check_Button(WB, y, 2*WB, BH,
+                                                     "Refine partition");
+      o->value(CTX.mesh.partition_options.refine_partition);
+      o->align(FL_ALIGN_RIGHT);
+    }
+    {
+      Fl_Check_Button *const o = new Fl_Check_Button(2*WB + 2*BB, y, 2*WB, BH,
+                                                     "Internal vertices");
+      o->value(CTX.mesh.partition_options.internal_vertices);
+      o->align(FL_ALIGN_RIGHT);
+    }
+    y += BH;
+    {
+      Fl_Check_Button *const o = new Fl_Check_Button(WB, y, 2*WB, BH,
+                                                     "Refine map");
+      o->value(CTX.mesh.partition_options.refine_map);
+      o->align(FL_ALIGN_RIGHT);
+    }
+    {
+      Fl_Check_Button *const o = new Fl_Check_Button(2*WB + 2*BB, y, 2*WB, BH,
+                                                     "Terminal propogation");
+      dlg.checkButtonTermProp = o;
+      o->value(CTX.mesh.partition_options.terminal_propogation);
+      o->callback((Fl_Callback *)partition_opt_spectralcheck_cb, &dlg);
+      o->align(FL_ALIGN_RIGHT);
+    }
+    y += BH + WB;
+    g->end();
+    g->hide();
+  }
+
+  // Metis options group [3]
+  y = yMain;
+  {
+    const int GH = BH + WB;
+    Fl_Group *g = new Fl_Group(0, y, w, GH);
+    // Algorithm
+    {
+      Fl_Choice *const o = new Fl_Choice(WB, y, BB, BH, "Algorithm");
+      dlg.choiceMetisAlg = o;
+      o->menu(metisAlgMenu);
+      o->value(CTX.mesh.partition_options.algorithm - 1);
+      o->align(FL_ALIGN_RIGHT);
+    }
+    // Advanced Button
+    {
+      Fl_Toggle_Button *const o = new Fl_Toggle_Button
+        (w - (WB + BB), y, BB, BH, "Advanced @-22->");
+      dlg.toggleButtonAdvMetis = o;
+      o->callback((Fl_Callback *)partition_select_groups_cb, &dlg);
+    }
+    y += BH + WB;
+    g->end();
+    g->hide();
+  }
+
+  // Metis advanced option group [4]
+  {
+    const int GH = 2 + WB + (BH + WB) + 2;
+    Fl_Group *g = new Fl_Group(0, y, w, GH);
+    // Box (line)
+    {
+      Fl_Box *const o = new Fl_Box(WB, y, w - 2*WB, 2);
+      o->box(FL_ENGRAVED_FRAME);
+      o->labeltype(FL_NO_LABEL);
+    }
+    y += 2 + WB + 1;  // +1 for multiline label
+    {
+      Fl_Choice *const o = new Fl_Choice(WB, y, BB, BH, "Edge matching");
+      o->menu(metisEdgeMatchingMenu);
+      o->value(CTX.mesh.partition_options.edge_matching - 1);
+      o->align(FL_ALIGN_RIGHT);
+    }
+    {
+      Fl_Choice *const o = new Fl_Choice(2*WB + 2*BB, y, BB, BH,
+                                         "Refinement\nalgorithm");
+      o->menu(metisRefineAlgMenu);
+      o->value(CTX.mesh.partition_options.refine_algorithm - 1);
+      o->align(FL_ALIGN_RIGHT);
+    }
+    y += BH + WB + 1;  // +1 for multiline label
+    g->end();
+    g->hide();
+  }
+  
+  // Dialog termination group [5]
+  {
+    const int GH = 2 + BH + 2*WB;
+    Fl_Group *g = new Fl_Group(0, y, w, GH);
+    // Box (line) [0]
+    {
+      Fl_Box *const o = new Fl_Box(WB, y, w - 2*WB, 2);
+      o->box(FL_ENGRAVED_FRAME);
+      o->labeltype(FL_NO_LABEL);
+    }
+    y += 2 + WB;
+    // Partition Button [1]
+    {
+      Fl_Return_Button *const o = new Fl_Return_Button
+        (w - 2*(WB + BB), y, BB, BH, "Partition");
+      o->callback((Fl_Callback *)partition_partition_cb);
+    }
+    // Cancel Button [2]
+    {
+      Fl_Button *const o = new Fl_Button(w - (WB + BB), y, BB, BH, "Cancel");
+      o->callback((Fl_Callback *)partition_cancel_cb);
+    }
+    y += BH + WB;
+    g->end();
+    g->show();
+  }
+
+  window->set_modal();
+  window->end();
+  window->hotspot(window);
+
+  partition_select_groups_cb(window->child(0), &dlg);
+  window->show();
+}
diff --git a/Fltk/GUI_Extras.h b/Fltk/GUI_Extras.h
index 9425a0b8731cadeb29b62946fdd176ae94a39a74..1586b10b54942e064db7f713627a99d1deb7e4eb 100644
--- a/Fltk/GUI_Extras.h
+++ b/Fltk/GUI_Extras.h
@@ -31,6 +31,7 @@ int unv_dialog(const char *filename);
 int bdf_dialog(const char *filename);
 int stl_dialog(const char *filename);
 int latex_dialog(const char *filename);
+int partition_dialog();
 
 #endif
 
diff --git a/Mesh/PartitionOptions.h b/Mesh/PartitionOptions.h
new file mode 100644
index 0000000000000000000000000000000000000000..1f663e559c3e3bc75a43ed9f176bf446139eb78d
--- /dev/null
+++ b/Mesh/PartitionOptions.h
@@ -0,0 +1,97 @@
+// Gmsh - Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#ifndef _PARTITIONOPTIONS_H_
+#define _PARTITIONOPTIONS_H_
+
+struct PartitionOptions
+{
+
+//--General
+  int partitioner;                      // 1 - Chaco
+                                        // 2 - METIS
+  int num_partitions;
+  int algorithm;                        // Chaco
+                                        //   1 - Multilevel-KL
+                                        //   2 - Spectral
+                                        //   3 - Inertial (Disabled)
+                                        //   4 - Linear
+                                        //   5 - Random
+                                        //   6 - Scattered
+                                        // METIS
+                                        //   1 - Recursive
+                                        //   2 = K-way
+
+//--Chaco
+
+  int architecture;                     // 0   - hypercube
+                                        // 1-3 - dimensional mesh parallel
+  int ndims_tot;                        // Number of hypercube dimensions */
+  int mesh_dims[3];                     // Number of partitions in each
+                                        // dimension for a dimensional
+                                        // architecture
+  double *goal;                         // Not-implemented (Weights vertices in
+                                        // a set)
+  int local_method;                     // 1 - Kernighan-Lin
+                                        // 2 - None
+  int rqi_flag;                         // Eigensolver for spectral partitioner
+                                        // 0 - Lanczos
+                                        // 1 - Multilevel RQI/Symmlq
+  int vmax;                             // Number of vertices in the coarsest
+                                        // graph.
+  int ndims;                            // Number of divisions at each stage
+                                        // 1 - Bisection
+                                        // 2 - Quadrisection
+                                        // 3 - Octasection
+  double eigtol;                        // Tolerance to the eigensolver
+  long seed;                            // RNG seed
+
+  // parameters
+  int refine_partition;                 // Refine partitions at each level
+  int internal_vertices;                // Increase internal vertices
+  int refine_map;                       // Refine processor mapping
+  int terminal_propogation;             // Run with terminal propogation
+
+//--METIS
+
+  int edge_matching;                    // 1 - Random matching
+                                        // 2 - Heavy-edge matching
+                                        // 3 - Sorted heavy-edge matching
+  int refine_algorithm;                 // 1 - Random boundary refinement
+                                        // 2 - Greedy boundary refinement
+                                        // 3 - Random boundary refinement (with
+                                        //     minimization of connectivity
+                                        //     along sub-domains)
+
+//--Default values (overridden by Common/DefaultOptions.h)
+
+  PartitionOptions()
+    :
+    partitioner(1),
+    num_partitions(4),
+    algorithm(1),
+    architecture(1),
+    ndims_tot(2),
+    goal(0),
+    local_method(1),
+    rqi_flag(1),
+    vmax(250),
+    ndims(1),
+    eigtol(1.E-3),
+    seed(7654321L),
+    refine_partition(false),
+    internal_vertices(true),
+    refine_map(true),
+    terminal_propogation(true),
+    edge_matching(3),
+    refine_algorithm(3)
+  {
+    mesh_dims[0] = 4;
+    mesh_dims[1] = 1;
+    mesh_dims[2] = 1;
+  }
+};
+
+#endif