OGS
PartitionMesh.cpp File Reference

Detailed Description

A tool for mesh partitioning.

Date
2016.05

Definition in file PartitionMesh.cpp.

#include <spdlog/spdlog.h>
#include <tclap/CmdLine.h>
#include "BaseLib/CPUTime.h"
#include "BaseLib/FileTools.h"
#include "BaseLib/MPI.h"
#include "BaseLib/RunTime.h"
#include "InfoLib/GitInfo.h"
#include "MeshLib/IO/readMeshFromFile.h"
#include "Metis.h"
#include "NodeWiseMeshPartitioner.h"
Include dependency graph for PartitionMesh.cpp:

Go to the source code of this file.

Functions

int main (int argc, char *argv[])
 

Function Documentation

◆ main()

int main ( int argc,
char * argv[] )

Definition at line 29 of file PartitionMesh.cpp.

30{
31 TCLAP::CmdLine cmd(
32 "Partition a mesh for parallel computing."
33 "The tasks of this tool are in twofold:\n"
34 "1. Convert mesh file to the input file of the partitioning tool,\n"
35 "2. Partition a mesh using the partitioning tool,\n"
36 "\tcreate the mesh data of each partition,\n"
37 "\trenumber the node indices of each partition,\n"
38 "\tand output the results for parallel computing.\n"
39 "Note: If this tool is installed as a system command,\n"
40 "\tthe command must be run with its full path.\n\n"
41 "OpenGeoSys-6 software, version " +
43 ".\n"
44 "Copyright (c) 2012-2024, OpenGeoSys Community "
45 "(http://www.opengeosys.org)",
47 TCLAP::ValueArg<std::string> mesh_input(
48 "i", "mesh-input-file",
49 "the name of the file containing the input mesh", true, "",
50 "file name of input mesh");
51 cmd.add(mesh_input);
52
53 TCLAP::ValueArg<std::string> metis_mesh_input(
54 "x", "metis-mesh-input-file",
55 "base name (without .mesh extension) of the file containing the metis "
56 "input mesh",
57 false, "",
58 "base name (without .mesh extension) of the file containing the metis "
59 "input mesh");
60 cmd.add(metis_mesh_input);
61
62 TCLAP::ValueArg<std::string> output_directory_arg(
63 "o", "output", "directory name for the output files", false, "",
64 "directory");
65 cmd.add(output_directory_arg);
66
67 TCLAP::ValueArg<int> nparts("n", "np", "the number of partitions", false, 2,
68 "integer");
69 cmd.add(nparts);
70
71 TCLAP::SwitchArg ogs2metis_flag(
72 "s", "ogs2metis",
73 "Indicator to convert the ogs mesh file to METIS input file", cmd,
74 false);
75
76 TCLAP::SwitchArg exe_metis_flag(
77 "m", "exe_metis", "Call mpmetis inside the programme via system().",
78 false);
79 cmd.add(exe_metis_flag);
80
81 TCLAP::ValueArg<std::string> log_level_arg(
82 "l", "log-level",
83 "the verbosity of logging messages: none, error, warn, info, debug, "
84 "all",
85 false,
86#ifdef NDEBUG
87 "info",
88#else
89 "all",
90#endif
91 "LOG_LEVEL");
92 cmd.add(log_level_arg);
93
94 // All the remaining arguments are used as file names for boundary/subdomain
95 // meshes.
96 TCLAP::UnlabeledMultiArg<std::string> other_meshes_filenames_arg(
97 "other_meshes_filenames", "mesh file names.", false, "file");
98 cmd.add(other_meshes_filenames_arg);
99
100 cmd.parse(argc, argv);
101
102 BaseLib::MPI::Setup mpi_setup(argc, argv);
103
104 BaseLib::setConsoleLogLevel(log_level_arg.getValue());
105 spdlog::set_pattern("%^%l:%$ %v");
106 spdlog::set_error_handler(
107 [](const std::string& msg)
108 {
109 std::cerr << "spdlog error: " << msg << std::endl;
110 OGS_FATAL("spdlog logger error occurred.");
111 });
112
113 const auto output_directory = output_directory_arg.getValue();
114 BaseLib::createOutputDirectory(output_directory);
115
116 BaseLib::RunTime run_timer;
117 run_timer.start();
118 BaseLib::CPUTime CPU_timer;
119 CPU_timer.start();
120
121 const std::string input_file_name_wo_extension =
122 BaseLib::dropFileExtension(mesh_input.getValue());
123 std::unique_ptr<MeshLib::Mesh> mesh_ptr(
124 MeshLib::IO::readMeshFromFile(input_file_name_wo_extension + ".vtu"));
125 INFO("Mesh '{:s}' read: {:d} nodes, {:d} elements.",
126 mesh_ptr->getName(),
127 mesh_ptr->getNumberOfNodes(),
128 mesh_ptr->getNumberOfElements());
129
130 std::string const output_file_name_wo_extension = BaseLib::joinPaths(
131 output_directory,
132 BaseLib::extractBaseNameWithoutExtension(mesh_input.getValue()));
133
134 if (ogs2metis_flag.getValue())
135 {
136 INFO("Write the mesh into METIS input file.");
137 ApplicationUtils::writeMETIS(mesh_ptr->getElements(),
138 output_file_name_wo_extension + ".mesh");
139 INFO("Total runtime: {:g} s.", run_timer.elapsed());
140 INFO("Total CPU time: {:g} s.", CPU_timer.elapsed());
141
142 return EXIT_SUCCESS;
143 }
144
146 nparts.getValue(), std::move(mesh_ptr));
147
148 const int num_partitions = nparts.getValue();
149
150 if (num_partitions < 1)
151 {
152 OGS_FATAL("Number of partitions must be positive.");
153 }
154
155 if (num_partitions == 1)
156 {
157 OGS_FATAL(
158 "Partitioning the mesh into one domain is unnecessary because OGS "
159 "reads vtu mesh data directly when called with 'mpirun bin/ogs "
160 "-np=1'.");
161 }
162
163 auto metis_mesh = output_file_name_wo_extension;
164 if (metis_mesh_input.getValue() != "")
165 {
166 metis_mesh = metis_mesh_input.getValue();
167 }
168
169 // Execute mpmetis via system(...)
170 if (exe_metis_flag.getValue())
171 {
172 INFO("METIS is running ...");
173 const std::string exe_name = argv[0];
174 const std::string exe_path = BaseLib::extractPath(exe_name);
175 INFO("Path to mpmetis is: \n\t{:s}", exe_path);
176
177 const std::string mpmetis_com =
178 BaseLib::joinPaths(exe_path, "mpmetis") + " -gtype=nodal " + "\"" +
179 metis_mesh + ".mesh" + "\" " + std::to_string(nparts.getValue());
180
181 INFO("Running: {:s}", mpmetis_com);
182 const int status = system(mpmetis_com.c_str());
183 if (status != 0)
184 {
185 INFO("Failed in system calling.");
186 INFO("Return value of system call {:d} ", status);
187 return EXIT_FAILURE;
188 }
189 }
190 mesh_partitioner.resetPartitionIdsForNodes(
191 readMetisData(metis_mesh, num_partitions,
192 mesh_partitioner.mesh().getNumberOfNodes()));
193
194 // Remove metis partitioning files only if metis was run internally.
195 if (exe_metis_flag.getValue())
196 {
197 removeMetisPartitioningFiles(metis_mesh, num_partitions);
198 }
199
200 INFO("Partitioning the mesh in the node wise way ...");
201 mesh_partitioner.partitionByMETIS();
202
203 INFO("Partitioning other meshes according to the main mesh partitions.");
204 for (auto const& filename : other_meshes_filenames_arg.getValue())
205 {
206 std::unique_ptr<MeshLib::Mesh> mesh(
208 INFO("Mesh '{:s}' from file '{:s}' read: {:d} nodes, {:d} elements.",
209 mesh->getName(), filename, mesh->getNumberOfNodes(),
210 mesh->getNumberOfElements());
211
212 std::string const other_mesh_output_file_name_wo_extension =
214 output_directory,
216 auto partitions = mesh_partitioner.partitionOtherMesh(*mesh);
217
218 auto partitioned_properties = partitionProperties(mesh, partitions);
219 mesh_partitioner.renumberBulkIdsProperty(partitions,
220 partitioned_properties);
221
222 mesh_partitioner.writeOtherMesh(
223 other_mesh_output_file_name_wo_extension, partitions,
224 partitioned_properties);
225 }
226
227 BaseLib::RunTime io_run_timer;
228 io_run_timer.start();
229 mesh_partitioner.write(output_file_name_wo_extension);
230 INFO("Writing the partitions data into binary files took {:g} s",
231 io_run_timer.elapsed());
232
233 INFO("Total runtime: {:g} s.", run_timer.elapsed());
234 INFO("Total CPU time: {:g} s.", CPU_timer.elapsed());
235
236 return EXIT_SUCCESS;
237}
#define OGS_FATAL(...)
Definition Error.h:26
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:35
std::string getValue(std::string const &line, std::string const &val_name, bool is_string)
Count CPU time.
Definition CPUTime.h:23
void start()
Start the timer.
Definition CPUTime.h:26
double elapsed() const
Get the elapsed time after started.
Definition CPUTime.h:29
Count the running time.
Definition RunTime.h:29
double elapsed() const
Get the elapsed time in seconds.
Definition RunTime.h:42
void start()
Start the timer.
Definition RunTime.h:32
void writeMETIS(std::vector< MeshLib::Element * > const &elements, const std::string &file_name)
Definition Metis.cpp:19
MeshLib::Properties partitionProperties(std::unique_ptr< MeshLib::Mesh > const &mesh, std::vector< Partition > &partitions)
Partition existing properties and add vtkGhostType cell data array property.
void removeMetisPartitioningFiles(std::string const &file_name_base, long const number_of_partitions)
Definition Metis.cpp:90
std::vector< std::size_t > readMetisData(const std::string &file_name_base, long const number_of_partitions, std::size_t const number_of_nodes)
Definition Metis.cpp:45
void setConsoleLogLevel(std::string const &level_string)
Definition Logging.cpp:37
std::string extractPath(std::string const &pathname)
std::string extractBaseNameWithoutExtension(std::string const &pathname)
std::string dropFileExtension(std::string const &filename)
std::string joinPaths(std::string const &pathA, std::string const &pathB)
bool createOutputDirectory(std::string const &dir)
GITINFOLIB_EXPORT const std::string ogs_version
MeshLib::Mesh * readMeshFromFile(const std::string &file_name, bool const compute_element_neighbors)

References BaseLib::createOutputDirectory(), BaseLib::dropFileExtension(), BaseLib::CPUTime::elapsed(), BaseLib::RunTime::elapsed(), BaseLib::extractBaseNameWithoutExtension(), BaseLib::extractPath(), MeshLib::Mesh::getNumberOfNodes(), INFO(), BaseLib::joinPaths(), ApplicationUtils::NodeWiseMeshPartitioner::mesh(), OGS_FATAL, GitInfoLib::GitInfo::ogs_version, ApplicationUtils::NodeWiseMeshPartitioner::partitionByMETIS(), ApplicationUtils::NodeWiseMeshPartitioner::partitionOtherMesh(), ApplicationUtils::partitionProperties(), MeshLib::IO::readMeshFromFile(), ApplicationUtils::readMetisData(), ApplicationUtils::removeMetisPartitioningFiles(), ApplicationUtils::NodeWiseMeshPartitioner::renumberBulkIdsProperty(), ApplicationUtils::NodeWiseMeshPartitioner::resetPartitionIdsForNodes(), BaseLib::setConsoleLogLevel(), BaseLib::CPUTime::start(), BaseLib::RunTime::start(), ApplicationUtils::NodeWiseMeshPartitioner::write(), ApplicationUtils::writeMETIS(), and ApplicationUtils::NodeWiseMeshPartitioner::writeOtherMesh().