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 <filesystem>
#include <mpi.h>
#include "BaseLib/CPUTime.h"
#include "BaseLib/FileTools.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 34 of file PartitionMesh.cpp.

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

References 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(), WARN(), ApplicationUtils::NodeWiseMeshPartitioner::write(), ApplicationUtils::writeMETIS(), and ApplicationUtils::NodeWiseMeshPartitioner::writeOtherMesh().