diff --git a/framework/include/actions/PartitionerAction.h b/framework/include/actions/PartitionerAction.h new file mode 100644 index 000000000000..2b55256ce418 --- /dev/null +++ b/framework/include/actions/PartitionerAction.h @@ -0,0 +1,37 @@ +/****************************************************************/ +/* DO NOT MODIFY THIS HEADER */ +/* MOOSE - Multiphysics Object Oriented Simulation Environment */ +/* */ +/* (c) 2010 Battelle Energy Alliance, LLC */ +/* ALL RIGHTS RESERVED */ +/* */ +/* Prepared by Battelle Energy Alliance, LLC */ +/* Under Contract No. DE-AC07-05ID14517 */ +/* With the U. S. Department of Energy */ +/* */ +/* See COPYRIGHT for full restrictions */ +/****************************************************************/ + +#ifndef PARTITIONERACTION_H +#define PARTITIONERACTION_H + +#include "Action.h" + +class PartitionerAction; + +template<> +InputParameters validParams(); + + +class PartitionerAction: public Action +{ +public: + PartitionerAction(InputParameters params); + + virtual void act(); + +protected: + MooseEnum _partitioner_type; +}; + +#endif //PartitionerAction_H diff --git a/framework/include/mesh/MooseMesh.h b/framework/include/mesh/MooseMesh.h index 40969e154ceb..c8b545869746 100644 --- a/framework/include/mesh/MooseMesh.h +++ b/framework/include/mesh/MooseMesh.h @@ -681,6 +681,12 @@ class MooseMesh : MooseMesh::MortarInterface * getMortarInterfaceByName(const std::string name); MooseMesh::MortarInterface * getMortarInterface(BoundaryID master, BoundaryID slave); + /** + * Setter and getter for custom partitioner + */ + Partitioner * getCustomPartitioner() const; + void setCustomPartitioner(Partitioner * custom_partitioner); + protected: /// Can be set to PARALLEL, SERIAL, or DEFAULT. Determines whether /// the underlying libMesh mesh is a SerialMesh or ParallelMesh. @@ -699,6 +705,9 @@ class MooseMesh : MooseEnum _partitioner_name; bool _partitioner_overridden; + /// The custom partitioner + Partitioner * _custom_partitioner; + /// Convenience enums enum { X = 0, diff --git a/framework/src/actions/PartitionerAction.C b/framework/src/actions/PartitionerAction.C new file mode 100644 index 000000000000..dd175fdd057f --- /dev/null +++ b/framework/src/actions/PartitionerAction.C @@ -0,0 +1,47 @@ +/****************************************************************/ +/* DO NOT MODIFY THIS HEADER */ +/* MOOSE - Multiphysics Object Oriented Simulation Environment */ +/* */ +/* (c) 2010 Battelle Energy Alliance, LLC */ +/* ALL RIGHTS RESERVED */ +/* */ +/* Prepared by Battelle Energy Alliance, LLC */ +/* Under Contract No. DE-AC07-05ID14517 */ +/* With the U. S. Department of Energy */ +/* */ +/* See COPYRIGHT for full restrictions */ +/****************************************************************/ + +#include "PartitionerAction.h" + +#include "FEProblem.h" +#include "MooseEnum.h" + +#include "libmesh/linear_partitioner.h" + +template<> +InputParameters validParams() +{ + InputParameters params = validParams(); + MooseEnum partitioning("linear=0", "linear"); + + params.addParam ("partitioner", partitioning, "The class name of the partitioner you want to use."); + return params; +} + +PartitionerAction::PartitionerAction(InputParameters params) : + Action(params), + _partitioner_type(getParam("partitioner")) +{ +} + +void +PartitionerAction::act() +{ + switch (_partitioner_type) + { + case 0: + _mesh->setCustomPartitioner(new LinearPartitioner()); + break; + } +} diff --git a/framework/src/actions/SetupMeshAction.C b/framework/src/actions/SetupMeshAction.C index 7d14b524a8e4..cac44540d339 100644 --- a/framework/src/actions/SetupMeshAction.C +++ b/framework/src/actions/SetupMeshAction.C @@ -137,23 +137,26 @@ void SetupMeshAction::act() { // Create the mesh object and tell it to build itself - _mesh = MooseSharedNamespace::static_pointer_cast(_factory.create(_type, "mesh", _moose_object_pars)); - _mesh->init(); - - if (isParamValid("displacements")) + if (_current_task == "setup_mesh") + _mesh = MooseSharedNamespace::static_pointer_cast(_factory.create(_type, "mesh", _moose_object_pars)); + else if (_current_task == "init_mesh") { - // Create the displaced mesh - _displaced_mesh = MooseSharedNamespace::static_pointer_cast(_factory.create(_type, "displaced_mesh", _moose_object_pars)); - _displaced_mesh->init(); + _mesh->init(); - std::vector displacements = getParam >("displacements"); - if (displacements.size() != _displaced_mesh->dimension()) - mooseError("Number of displacements and dimension of mesh MUST be the same!"); - } + if (isParamValid("displacements")) + { + // Create the displaced mesh + _displaced_mesh = MooseSharedNamespace::static_pointer_cast(_factory.create(_type, "displaced_mesh", _moose_object_pars)); + _displaced_mesh->init(); - setupMesh(_mesh.get()); + std::vector displacements = getParam >("displacements"); + if (displacements.size() != _displaced_mesh->dimension()) + mooseError("Number of displacements and dimension of mesh MUST be the same!"); + } - if (_displaced_mesh) - setupMesh(_displaced_mesh.get()); -} + setupMesh(_mesh.get()); + if (_displaced_mesh) + setupMesh(_displaced_mesh.get()); + } +} diff --git a/framework/src/base/Moose.C b/framework/src/base/Moose.C index 94598b3b8918..0bc1d47a7347 100644 --- a/framework/src/base/Moose.C +++ b/framework/src/base/Moose.C @@ -349,6 +349,7 @@ #include "AddMaterialAction.h" #include "GlobalParamsAction.h" #include "AdaptivityAction.h" +#include "PartitionerAction.h" #include "SetupDampersAction.h" #include "CheckIntegrityAction.h" #include "SetupQuadratureAction.h" @@ -759,6 +760,7 @@ addActionTypes(Syntax & syntax) registerMooseObjectTask("determine_system_type", Executioner, true); registerMooseObjectTask("setup_mesh", MooseMesh, false); + registerMooseObjectTask("init_mesh", MooseMesh, false); registerMooseObjectTask("add_mesh_modifier", MeshModifier, false); registerMooseObjectTask("add_kernel", Kernel, false); @@ -817,6 +819,7 @@ addActionTypes(Syntax & syntax) registerTask("uniform_refine_mesh", false); registerTask("prepare_mesh", false); registerTask("setup_mesh_complete", false); // calls prepare + registerTask("setup_partitioner", false); registerTask("init_displaced_problem", false); @@ -871,6 +874,8 @@ addActionTypes(Syntax & syntax) "(setup_recover_file_base)" "(check_copy_nodal_vars)" "(setup_mesh)" +"(setup_partitioner)" +"(init_mesh)" "(prepare_mesh)" "(add_mesh_modifier)" "(add_mortar_interface)" @@ -956,6 +961,7 @@ registerActions(Syntax & syntax, ActionFactory & action_factory) registerAction(SetupPostprocessorDataAction, "setup_postprocessor_data"); registerAction(SetupMeshAction, "setup_mesh"); + registerAction(SetupMeshAction, "init_mesh"); registerAction(SetupMeshCompleteAction, "prepare_mesh"); registerAction(AddMeshModifierAction, "add_mesh_modifier"); registerAction(AddMortarInterfaceAction, "add_mortar_interface"); @@ -1024,6 +1030,7 @@ registerActions(Syntax & syntax, ActionFactory & action_factory) registerAction(AdaptivityAction, "setup_adaptivity"); #endif + registerAction(PartitionerAction, "setup_partitioner"); registerAction(AddDiracKernelAction, "add_dirac_kernel"); registerAction(SetupDebugAction, "setup_debug"); registerAction(SetupResidualDebugAction, "setup_residual_debug"); diff --git a/framework/src/base/MooseApp.C b/framework/src/base/MooseApp.C index ffbc3fa409b7..e394a856a8ea 100644 --- a/framework/src/base/MooseApp.C +++ b/framework/src/base/MooseApp.C @@ -456,6 +456,8 @@ MooseApp::meshOnly(std::string mesh_file_name) */ _action_warehouse.executeActionsWithAction("set_global_params"); _action_warehouse.executeActionsWithAction("setup_mesh"); + _action_warehouse.executeActionsWithAction("setup_partitioner"); + _action_warehouse.executeActionsWithAction("init_mesh"); _action_warehouse.executeActionsWithAction("prepare_mesh"); _action_warehouse.executeActionsWithAction("add_mesh_modifier"); _action_warehouse.executeActionsWithAction("execute_mesh_modifiers"); diff --git a/framework/src/mesh/MooseMesh.C b/framework/src/mesh/MooseMesh.C index 672999a9c3cd..2e03defe0fd0 100644 --- a/framework/src/mesh/MooseMesh.C +++ b/framework/src/mesh/MooseMesh.C @@ -72,7 +72,7 @@ InputParameters validParams() "In particular you must supply this for GMSH meshes. " "Note: This is completely ignored for ExodusII meshes!"); - MooseEnum partitioning("default=-3 metis=-2 parmetis=-1 linear=0 centroid hilbert_sfc morton_sfc", "default"); + MooseEnum partitioning("default=-3 metis=-2 parmetis=-1 linear=0 centroid hilbert_sfc morton_sfc custom", "default"); params.addParam("partitioner", partitioning, "Specifies a mesh partitioner to use when splitting the mesh for a parallel computation."); MooseEnum direction("x y z radial"); params.addParam("centroid_partitioner_direction", direction, "Specifies the sort direction if using the centroid partitioner. Available options: x, y, z, radial"); @@ -155,51 +155,6 @@ MooseMesh::MooseMesh(const InputParameters & parameters) : } else _mesh = new SerialMesh(_communicator, dim); - - // Set the partitioner - switch (_partitioner_name) - { - case -3: // default - // We'll use the default partitioner, but notify the user of which one is being used... - if (_use_parallel_mesh) - _partitioner_name = "parmetis"; - else - _partitioner_name = "metis"; - break; - - // No need to explicitily create the metis or parmetis partitioners, - // They are the default for serial and parallel mesh respectively - case -2: // metis - case -1: // parmetis - break; - - case 0: // linear - getMesh().partitioner().reset(new LinearPartitioner); - break; - case 1: // centroid - { - if (!isParamValid("centroid_partitioner_direction")) - mooseError("If using the centroid partitioner you _must_ specify centroid_partitioner_direction!"); - - MooseEnum direction = getParam("centroid_partitioner_direction"); - - if (direction == "x") - getMesh().partitioner().reset(new CentroidPartitioner(CentroidPartitioner::X)); - else if (direction == "y") - getMesh().partitioner().reset(new CentroidPartitioner(CentroidPartitioner::Y)); - else if (direction == "z") - getMesh().partitioner().reset(new CentroidPartitioner(CentroidPartitioner::Z)); - else if (direction == "radial") - getMesh().partitioner().reset(new CentroidPartitioner(CentroidPartitioner::RADIAL)); - break; - } - case 2: // hilbert_sfc - getMesh().partitioner().reset(new HilbertSFCPartitioner); - break; - case 3: // morton_sfc - getMesh().partitioner().reset(new MortonSFCPartitioner); - break; - } } MooseMesh::MooseMesh(const MooseMesh & other_mesh) : @@ -211,6 +166,7 @@ MooseMesh::MooseMesh(const MooseMesh & other_mesh) : _mesh(other_mesh.getMesh().clone().release()), _partitioner_name(other_mesh._partitioner_name), _partitioner_overridden(other_mesh._partitioner_overridden), + _custom_partitioner(other_mesh.getCustomPartitioner()), _uniform_refine_level(other_mesh.uniformRefineLevel()), _is_changed(false), _is_nemesis(false), @@ -1743,6 +1699,56 @@ MooseMesh::getNormalByBoundaryID(BoundaryID id) const void MooseMesh::init() { + // Set the partitioner + switch (_partitioner_name) + { + case -3: // default + // We'll use the default partitioner, but notify the user of which one is being used... + if (_use_parallel_mesh) + _partitioner_name = "parmetis"; + else + _partitioner_name = "metis"; + break; + + // No need to explicitily create the metis or parmetis partitioners, + // They are the default for serial and parallel mesh respectively + case -2: // metis + case -1: // parmetis + break; + + case 0: // linear + getMesh().partitioner().reset(new LinearPartitioner); + break; + case 1: // centroid + { + if (!isParamValid("centroid_partitioner_direction")) + mooseError("If using the centroid partitioner you _must_ specify centroid_partitioner_direction!"); + + MooseEnum direction = getParam("centroid_partitioner_direction"); + + if (direction == "x") + getMesh().partitioner().reset(new CentroidPartitioner(CentroidPartitioner::X)); + else if (direction == "y") + getMesh().partitioner().reset(new CentroidPartitioner(CentroidPartitioner::Y)); + else if (direction == "z") + getMesh().partitioner().reset(new CentroidPartitioner(CentroidPartitioner::Z)); + else if (direction == "radial") + getMesh().partitioner().reset(new CentroidPartitioner(CentroidPartitioner::RADIAL)); + break; + } + case 2: // hilbert_sfc + getMesh().partitioner().reset(new HilbertSFCPartitioner); + break; + case 3: // morton_sfc + getMesh().partitioner().reset(new MortonSFCPartitioner); + break; + case 4: // custom + if (!_custom_partitioner) + mooseError("If using partitioner type custom you must explicitly provide a partitioner in your input file!"); + getMesh().partitioner().reset(_custom_partitioner); + break; + } + if (_app.isRecovering() && _allow_recovery && _app.isUltimateMaster()) // For now, only read the recovery mesh on the Ultimate Master.. sub-apps need to just build their mesh like normal getMesh().read(_app.getRecoverFileBase() + "_mesh.cpr"); @@ -2166,6 +2172,19 @@ MooseMesh::getMortarInterface(BoundaryID master, BoundaryID slave) mooseError("Requesting non-existing mortar interface (master = " << master << ", slave = " << slave << ")."); } +Partitioner * +MooseMesh::getCustomPartitioner() const +{ + return _custom_partitioner; +} + + +void +MooseMesh::setCustomPartitioner(Partitioner * custom_partitioner) +{ + _custom_partitioner = custom_partitioner; +} + void MooseMesh::addMortarInterface(const std::string & name, BoundaryName master, BoundaryName slave, SubdomainName domain_name) { diff --git a/framework/src/parser/MooseSyntax.C b/framework/src/parser/MooseSyntax.C index d7c9d6ea9439..ec69373047b9 100644 --- a/framework/src/parser/MooseSyntax.C +++ b/framework/src/parser/MooseSyntax.C @@ -104,6 +104,8 @@ void associateSyntax(Syntax & syntax, ActionFactory & action_factory) syntax.registerActionSyntax("AdaptivityAction", "Executioner/Adaptivity"); #endif + syntax.registerActionSyntax("PartitionerAction", "Partitioner"); + syntax.registerActionSyntax("AddDiracKernelAction", "DiracKernels/*"); syntax.registerActionSyntax("AddDGKernelAction", "DGKernels/*"); diff --git a/test/tests/mesh/custom_partitioner/custom_linear_partitioner_test.i b/test/tests/mesh/custom_partitioner/custom_linear_partitioner_test.i new file mode 100644 index 000000000000..2f8fd1c5b5f2 --- /dev/null +++ b/test/tests/mesh/custom_partitioner/custom_linear_partitioner_test.i @@ -0,0 +1,87 @@ +[Mesh] + type = GeneratedMesh + dim = 2 + + nx = 10 + ny = 100 + + xmin = 0.0 + xmax = 1.0 + + ymin = 0.0 + ymax = 10.0 + + partitioner = custom + + + distribution = serial +[] + +[Partitioner] + partitioner_type = linear +[] + +[Variables] + active = 'u' + + [./u] + order = FIRST + family = LAGRANGE + [../] +[] + +[AuxVariables] + [./proc_id] + order = CONSTANT + family = MONOMIAL + [../] +[] + +[Kernels] + active = 'diff' + + [./diff] + type = Diffusion + variable = u + [../] +[] + +[AuxKernels] + [./proc_id] + type = ProcessorIDAux + variable = proc_id + [../] +[] + +[BCs] + active = 'left right' + + [./left] + type = DirichletBC + variable = u + boundary = 3 + value = 0 + [../] + + [./right] + type = DirichletBC + variable = u + boundary = 1 + value = 1 + [../] +[] + +[Executioner] + type = Steady + + # Preconditioned JFNK (default) + solve_type = 'PJFNK' +[] + +[Outputs] + file_base = out + [./exodus] + type = Exodus + elemental_as_nodal = true + [../] +[] diff --git a/test/tests/mesh/custom_partitioner/linear_partitioner_test.i b/test/tests/mesh/custom_partitioner/linear_partitioner_test.i new file mode 100644 index 000000000000..978a69a576e6 --- /dev/null +++ b/test/tests/mesh/custom_partitioner/linear_partitioner_test.i @@ -0,0 +1,82 @@ +[Mesh] + type = GeneratedMesh + dim = 2 + + nx = 10 + ny = 100 + + xmin = 0.0 + xmax = 1.0 + + ymin = 0.0 + ymax = 10.0 + + partitioner = linear + + distribution = serial +[] + +[Variables] + active = 'u' + + [./u] + order = FIRST + family = LAGRANGE + [../] +[] + +[AuxVariables] + [./proc_id] + order = CONSTANT + family = MONOMIAL + [../] +[] + +[Kernels] + active = 'diff' + + [./diff] + type = Diffusion + variable = u + [../] +[] + +[AuxKernels] + [./proc_id] + type = ProcessorIDAux + variable = proc_id + [../] +[] + +[BCs] + active = 'left right' + + [./left] + type = DirichletBC + variable = u + boundary = 3 + value = 0 + [../] + + [./right] + type = DirichletBC + variable = u + boundary = 1 + value = 1 + [../] +[] + +[Executioner] + type = Steady + + # Preconditioned JFNK (default) + solve_type = 'PJFNK' +[] + +[Outputs] + file_base = out + [./exodus] + type = Exodus + elemental_as_nodal = true + [../] +[]