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