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 <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 32 of file PartitionMesh.cpp.

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