diff --git a/framework/include/actions/SplitMeshAction.h b/framework/include/actions/SplitMeshAction.h new file mode 100644 index 000000000000..ffec3c3e4391 --- /dev/null +++ b/framework/include/actions/SplitMeshAction.h @@ -0,0 +1,30 @@ +//* This file is part of the MOOSE framework +//* https://www.mooseframework.org +//* +//* All rights reserved, see COPYRIGHT for full restrictions +//* https://github.com/idaholab/moose/blob/master/COPYRIGHT +//* +//* Licensed under LGPL 2.1, please see LICENSE for details +//* https://www.gnu.org/licenses/lgpl-2.1.html + +#ifndef SPLITMESHACTION_H +#define SPLITMESHACTION_H + +#include "Action.h" + +#include + +class SplitMeshAction; + +template <> +InputParameters validParams(); + +class SplitMeshAction : public Action +{ +public: + SplitMeshAction(InputParameters params); + + virtual void act() override; +}; + +#endif // SPLITMESHACTION_H diff --git a/framework/include/mesh/FileMesh.h b/framework/include/mesh/FileMesh.h index f29c3c60b05d..f6f11272e614 100644 --- a/framework/include/mesh/FileMesh.h +++ b/framework/include/mesh/FileMesh.h @@ -34,7 +34,7 @@ class FileMesh : public MooseMesh // Get/Set Filename (for meshes read from a file) void setFileName(const std::string & file_name) { _file_name = file_name; } - const std::string & getFileName() const { return _file_name; } + virtual std::string getFileName() const override { return _file_name; } protected: /// the file_name from whence this mesh came diff --git a/framework/include/mesh/MooseMesh.h b/framework/include/mesh/MooseMesh.h index 2db863897dcb..8e3cf1394f01 100644 --- a/framework/include/mesh/MooseMesh.h +++ b/framework/include/mesh/MooseMesh.h @@ -812,6 +812,12 @@ class MooseMesh : public MooseObject, public Restartable */ virtual std::unique_ptr getPointLocator() const; + /** + * Returns the name of the mesh file read to produce this mesh if any or an empty string + * otherwise. + */ + virtual std::string getFileName() const { return ""; } + protected: /// Deprecated (DO NOT USE) std::vector> _ghosting_functors; @@ -966,9 +972,6 @@ class MooseMesh : public MooseObject, public Restartable /// The patch update strategy Moose::PatchUpdateType _patch_update_strategy; - /// file_name iff this mesh was read from a file - std::string _file_name; - /// Vector of all the Nodes in the mesh for determining when to add a new point std::vector _node_map; diff --git a/framework/include/mesh/TiledMesh.h b/framework/include/mesh/TiledMesh.h index 3ee0a2a4d780..73010fb84be8 100644 --- a/framework/include/mesh/TiledMesh.h +++ b/framework/include/mesh/TiledMesh.h @@ -27,6 +27,8 @@ class TiledMesh : public MooseMesh virtual void buildMesh() override; + virtual std::string getFileName() const override; + protected: const Real _x_width; const Real _y_width; diff --git a/framework/include/utils/MooseUtils.h b/framework/include/utils/MooseUtils.h index 11b825132272..f6d2e8d61208 100644 --- a/framework/include/utils/MooseUtils.h +++ b/framework/include/utils/MooseUtils.h @@ -110,6 +110,12 @@ void serialEnd(const libMesh::Parallel::Communicator & comm); */ bool hasExtension(const std::string & filename, std::string ext, bool strip_exodus_ext = false); +/** + * Removes any file extension from the fiven string s (i.e. any ".[extension]" suffix of s) and + * returns the result. + */ +std::string stripExtension(const std::string & s); + /** * Function for splitting path and filename * @param full_file A complete filename and path diff --git a/framework/src/actions/SetupMeshAction.C b/framework/src/actions/SetupMeshAction.C index 89672ac8f1d0..d6f58119d7d2 100644 --- a/framework/src/actions/SetupMeshAction.C +++ b/framework/src/actions/SetupMeshAction.C @@ -10,6 +10,7 @@ #include "SetupMeshAction.h" #include "MooseApp.h" #include "MooseMesh.h" +#include "FileMesh.h" #include "FEProblem.h" #include "ActionWarehouse.h" #include "Factory.h" @@ -155,6 +156,34 @@ SetupMeshAction::act() // Create the mesh object and tell it to build itself if (_current_task == "setup_mesh") { + // switch non-file meshes to be a file-mesh if using a pre-split mesh configuration. + if (_app.parameters().get("use_split")) + { + auto split_file = _app.parameters().get("split_file"); + if (_type != "FileMesh") + { + if (split_file == "") + mooseError("cannot use split mesh with non-file mesh without specifying --split-file on " + "command line"); + + _type = "FileMesh"; + auto new_pars = validParams(); + new_pars.set("file") = split_file; + new_pars.set("_moose_app") = _moose_object_pars.get("_moose_app"); + new_pars.set("parallel_type") = "distributed"; + _moose_object_pars = new_pars; + } + else + { + new_pars.set("parallel_type") = "distributed"; + if (split_file != "") + _moose_object_pars.set("file") = split_file; + else + _moose_object_pars.set("file") = + MooseUtils::stripExtension(_moose_object_pars.get("file")) + ".cpr"; + } + } + _mesh = _factory.create(_type, "mesh", _moose_object_pars); if (isParamValid("displacements")) _displaced_mesh = _factory.create(_type, "displaced_mesh", _moose_object_pars); diff --git a/framework/src/actions/SplitMeshAction.C b/framework/src/actions/SplitMeshAction.C new file mode 100644 index 000000000000..0ba4ba8b1e05 --- /dev/null +++ b/framework/src/actions/SplitMeshAction.C @@ -0,0 +1,55 @@ +//* This file is part of the MOOSE framework +//* https://www.mooseframework.org +//* +//* All rights reserved, see COPYRIGHT for full restrictions +//* https://github.com/idaholab/moose/blob/master/COPYRIGHT +//* +//* Licensed under LGPL 2.1, please see LICENSE for details +//* https://www.gnu.org/licenses/lgpl-2.1.html + +#include "SplitMeshAction.h" + +#include "MooseApp.h" +#include "MooseUtils.h" +#include "MooseMesh.h" +#include "libmesh/checkpoint_io.h" + +template <> +InputParameters +validParams() +{ + return validParams(); +} + +SplitMeshAction::SplitMeshAction(InputParameters params) : Action(params) {} + +void +SplitMeshAction::act() +{ + auto mesh = _app.actionWarehouse().mesh(); + + if (mesh->getFileName() == "" && _app.parameters().get("split_file") == "") + mooseError("Output mesh file name must be specified (with --split-file) when splitting " + "non-file-based meshes"); + + auto splitstr = _app.parameters().get("split_mesh"); + std::vector splits; + bool success = MooseUtils::tokenizeAndConvert(splitstr, splits, ", "); + if (!success) + mooseError("invalid argument for --split-file: '", splitstr, "'"); + + for (std::size_t i = 0; i < splits.size(); i++) + { + processor_id_type n = splits[i]; + Moose::out << "Splitting " << n << " ways..." << std::endl; + + auto cpr = libMesh::split_mesh(*mesh, n); + Moose::out << " - writing " << cpr->current_processor_ids().size() << " files per process..." + << std::endl; + cpr->binary() = true; + auto fname = MooseUtils::stripExtension(mesh->getFileName()) + ".cpr"; + if (mesh->getFileName() == "") + fname = _app.parameters().get("split_file"); + cpr->write(fname); + } +} diff --git a/framework/src/base/Moose.C b/framework/src/base/Moose.C index 9d127bc537ce..6a49f4006ede 100644 --- a/framework/src/base/Moose.C +++ b/framework/src/base/Moose.C @@ -449,6 +449,7 @@ #include "MaterialDerivativeTestAction.h" #include "AddRelationshipManager.h" #include "MeshOnlyAction.h" +#include "SplitMeshAction.h" // Outputs #ifdef LIBMESH_HAVE_EXODUS_API @@ -1161,6 +1162,7 @@ registerActions(Syntax & syntax, ActionFactory & action_factory) registerAction(SetupPostprocessorDataAction, "setup_postprocessor_data"); + registerAction(SplitMeshAction, "split_mesh"); registerAction(MeshOnlyAction, "mesh_only"); registerAction(SetupMeshAction, "setup_mesh"); registerAction(SetupMeshAction, "init_mesh"); diff --git a/framework/src/base/MooseApp.C b/framework/src/base/MooseApp.C index 31dfb29b983c..e3b60d855496 100644 --- a/framework/src/base/MooseApp.C +++ b/framework/src/base/MooseApp.C @@ -40,6 +40,7 @@ #include "libmesh/exodusII_io.h" #include "libmesh/mesh_refinement.h" #include "libmesh/string_to_enum.h" +#include "libmesh/checkpoint_io.h" // System include for dynamic library methods #include @@ -136,6 +137,19 @@ validParams() false, "The libMesh Mesh underlying MooseMesh should always be a DistributedMesh"); + params.addCommandLineParam( + "split_mesh", + "--split-mesh [splits]", + "comma-separated list of numbers of chunks to split the mesh into"); + + params.addCommandLineParam("split_file", + "--split-file [filename]", + "", + "optional name of split mesh file(s) to write/read"); + + params.addCommandLineParam( + "use_split", "--use-split", false, "use split distributed mesh files"); + params.addCommandLineParam( "refinements", "-r ", @@ -527,6 +541,12 @@ MooseApp::setupOptions() _syntax.addDependency("mesh_only", "setup_mesh_complete"); _action_warehouse.setFinalTask("mesh_only"); } + else if (isParamValid("split_mesh")) + { + _syntax.registerTaskName("split_mesh", true); + _syntax.addDependency("split_mesh", "setup_mesh_complete"); + _action_warehouse.setFinalTask("split_mesh"); + } _action_warehouse.build(); } else @@ -563,17 +583,17 @@ MooseApp::runInputFile() _action_warehouse.executeAllActions(); - if (isParamValid("mesh_only")) + if (isParamValid("mesh_only") || isParamValid("split_mesh")) _ready_to_exit = true; else if (getParam("list_constructed_objects")) { // TODO: ask multiapps for their constructed objects + _ready_to_exit = true; std::vector obj_list = _factory.getConstructedObjects(); Moose::out << "**START OBJECT DATA**\n"; for (const auto & name : obj_list) Moose::out << name << "\n"; Moose::out << "**END OBJECT DATA**\n" << std::endl; - _ready_to_exit = true; } } diff --git a/framework/src/mesh/TiledMesh.C b/framework/src/mesh/TiledMesh.C index 8b5c8f1a34bc..4c301b1a179d 100644 --- a/framework/src/mesh/TiledMesh.C +++ b/framework/src/mesh/TiledMesh.C @@ -81,6 +81,12 @@ TiledMesh::clone() const return *(new TiledMesh(*this)); } +std::string +TiledMesh::getFileName() const +{ + return getParam("file"); +} + void TiledMesh::buildMesh() { diff --git a/framework/src/utils/MooseUtils.C b/framework/src/utils/MooseUtils.C index ce3bf7aace5f..d63ed980d5dc 100644 --- a/framework/src/utils/MooseUtils.C +++ b/framework/src/utils/MooseUtils.C @@ -254,6 +254,15 @@ hasExtension(const std::string & filename, std::string ext, bool strip_exodus_ex return false; } +std::string +stripExtension(const std::string & s) +{ + auto pos = s.rfind("."); + if (pos != std::string::npos) + return s.substr(0, pos); + return s; +} + std::pair splitFileName(std::string full_file) {