OGS
PartitionMesh.cpp
Go to the documentation of this file.
1
15#include <tclap/CmdLine.h>
16
17#include "BaseLib/CPUTime.h"
18#include "BaseLib/FileTools.h"
19#include "BaseLib/Logging.h"
20#include "BaseLib/MPI.h"
21#include "BaseLib/RunTime.h"
23#include "InfoLib/GitInfo.h"
25#include "Metis.h"
27
28using namespace ApplicationUtils;
29
30int main(int argc, char* argv[])
31{
32 TCLAP::CmdLine cmd(
33 "Partition a mesh for parallel computing."
34 "The tasks of this tool are in twofold:\n"
35 "1. Convert mesh file to the input file of the partitioning tool,\n"
36 "2. Partition a mesh using the partitioning tool,\n"
37 "\tcreate the mesh data of each partition,\n"
38 "\trenumber the node indices of each partition,\n"
39 "\tand output the results for parallel computing.\n"
40 "Note: If this tool is installed as a system command,\n"
41 "\tthe command must be run with its full path.\n\n"
42 "OpenGeoSys-6 software, version " +
44 ".\n"
45 "Copyright (c) 2012-2025, OpenGeoSys Community "
46 "(http://www.opengeosys.org)",
48 TCLAP::ValueArg<std::string> mesh_input(
49 "i", "mesh-input-file",
50 "Input (.vtu). The name of the file containing the input mesh", true,
51 "", "INPUT_FILE");
52 cmd.add(mesh_input);
53
54 TCLAP::ValueArg<std::string> metis_mesh_input(
55 "x", "metis-mesh-input-file",
56 "Input (.mesh). Base name (without .mesh extension) of the file "
57 "containing the metis input mesh",
58 false, "", "BASE_FILENAME_INPUT");
59 cmd.add(metis_mesh_input);
60
61 TCLAP::ValueArg<std::string> output_directory_arg(
62 "o", "output", "Output. Directory name for the output files", false, "",
63 "OUTPUT_PATH");
64 cmd.add(output_directory_arg);
65
66 TCLAP::ValueArg<int> nparts("n", "np",
67 "the number of partitions, "
68 "(min = 0)",
69 false, 2, "N_PARTS");
70 cmd.add(nparts);
71
72 TCLAP::SwitchArg ogs2metis_flag(
73 "s", "ogs2metis",
74 "Indicator to convert the ogs mesh file to METIS input file", cmd,
75 false);
76
77 TCLAP::SwitchArg exe_metis_flag(
78 "m", "exe_metis", "Call mpmetis inside the programme via system().",
79 false);
80 cmd.add(exe_metis_flag);
81
82 auto log_level_arg = BaseLib::makeLogLevelArg();
83 cmd.add(log_level_arg);
84
85 // All the remaining arguments are used as file names for boundary/subdomain
86 // meshes.
87 TCLAP::UnlabeledMultiArg<std::string> other_meshes_filenames_arg(
88 "other_meshes_filenames", "mesh file names.", false, "file");
89 cmd.add(other_meshes_filenames_arg);
90
91 cmd.parse(argc, argv);
92
93 BaseLib::MPI::Setup mpi_setup(argc, argv);
94 BaseLib::initOGSLogger(log_level_arg.getValue());
95
96 const auto output_directory = output_directory_arg.getValue();
97 BaseLib::createOutputDirectory(output_directory);
98
99 BaseLib::RunTime run_timer;
100 run_timer.start();
101 BaseLib::CPUTime CPU_timer;
102 CPU_timer.start();
103
104 const std::string input_file_name_wo_extension =
105 BaseLib::dropFileExtension(mesh_input.getValue());
106 std::unique_ptr<MeshLib::Mesh> mesh_ptr(
107 MeshLib::IO::readMeshFromFile(input_file_name_wo_extension + ".vtu"));
108 INFO("Mesh '{:s}' read: {:d} nodes, {:d} elements.",
109 mesh_ptr->getName(),
110 mesh_ptr->getNumberOfNodes(),
111 mesh_ptr->getNumberOfElements());
112
113 std::string const output_file_name_wo_extension = BaseLib::joinPaths(
114 output_directory,
115 BaseLib::extractBaseNameWithoutExtension(mesh_input.getValue()));
116
117 if (ogs2metis_flag.getValue())
118 {
119 INFO("Write the mesh into METIS input file.");
120 ApplicationUtils::writeMETIS(mesh_ptr->getElements(),
121 output_file_name_wo_extension + ".mesh");
122 INFO("Total runtime: {:g} s.", run_timer.elapsed());
123 INFO("Total CPU time: {:g} s.", CPU_timer.elapsed());
124
125 return EXIT_SUCCESS;
126 }
127
129 nparts.getValue(), std::move(mesh_ptr));
130
131 const int num_partitions = nparts.getValue();
132
133 if (num_partitions < 1)
134 {
135 OGS_FATAL("Number of partitions must be positive.");
136 }
137
138 if (num_partitions == 1)
139 {
140 OGS_FATAL(
141 "Partitioning the mesh into one domain is unnecessary because OGS "
142 "reads vtu mesh data directly when called with 'mpirun bin/ogs "
143 "-np=1'.");
144 }
145
146 auto metis_mesh = output_file_name_wo_extension;
147 if (metis_mesh_input.getValue() != "")
148 {
149 metis_mesh = metis_mesh_input.getValue();
150 }
151
152 // Execute mpmetis via system(...)
153 if (exe_metis_flag.getValue())
154 {
155 INFO("METIS is running ...");
156 const std::string exe_name = argv[0];
157 const std::string exe_path = BaseLib::extractPath(exe_name);
158 INFO("Path to mpmetis is: \n\t{:s}", exe_path);
159
160 const std::string mpmetis_com =
161 BaseLib::joinPaths(exe_path, "mpmetis") + " -gtype=nodal " + "\"" +
162 metis_mesh + ".mesh" + "\" " + std::to_string(nparts.getValue());
163
164 INFO("Running: {:s}", mpmetis_com);
165 const int status = system(mpmetis_com.c_str());
166 if (status != 0)
167 {
168 INFO("Failed in system calling.");
169 INFO("Return value of system call {:d} ", status);
170 return EXIT_FAILURE;
171 }
172 }
173 mesh_partitioner.resetPartitionIdsForNodes(
174 readMetisData(metis_mesh, num_partitions,
175 mesh_partitioner.mesh().getNumberOfNodes()));
176
177 // Remove metis partitioning files only if metis was run internally.
178 if (exe_metis_flag.getValue())
179 {
180 removeMetisPartitioningFiles(metis_mesh, num_partitions);
181 }
182
183 INFO("Partitioning the mesh in the node wise way ...");
184 mesh_partitioner.partitionByMETIS();
185
186 INFO("Partitioning other meshes according to the main mesh partitions.");
187 for (auto const& filename : other_meshes_filenames_arg.getValue())
188 {
189 std::unique_ptr<MeshLib::Mesh> mesh(
191 INFO("Mesh '{:s}' from file '{:s}' read: {:d} nodes, {:d} elements.",
192 mesh->getName(), filename, mesh->getNumberOfNodes(),
193 mesh->getNumberOfElements());
194
195 std::string const other_mesh_output_file_name_wo_extension =
197 output_directory,
199 auto partitions = mesh_partitioner.partitionOtherMesh(*mesh);
200
201 auto partitioned_properties = partitionProperties(mesh, partitions);
202 mesh_partitioner.renumberBulkIdsProperty(partitions,
203 partitioned_properties);
204
205 mesh_partitioner.writeOtherMesh(
206 other_mesh_output_file_name_wo_extension, partitions,
207 partitioned_properties);
208 }
209
210 BaseLib::RunTime io_run_timer;
211 io_run_timer.start();
212 mesh_partitioner.write(output_file_name_wo_extension);
213 INFO("Writing the partitions data into binary files took {:g} s",
214 io_run_timer.elapsed());
215
216 INFO("Total runtime: {:g} s.", run_timer.elapsed());
217 INFO("Total CPU time: {:g} s.", CPU_timer.elapsed());
218
219 return EXIT_SUCCESS;
220}
Definition of the CPUTime class.
#define OGS_FATAL(...)
Definition Error.h:26
Filename manipulation routines.
Git information.
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:36
Declare a class to perform node wise mesh partitioning.
int main(int argc, char *argv[])
Definition of the RunTime class.
std::vector< Partition > partitionOtherMesh(MeshLib::Mesh const &mesh) const
void write(const std::string &file_name_base)
void renumberBulkIdsProperty(std::vector< Partition > const &partitions, MeshLib::Properties &partitioned_properties)
void resetPartitionIdsForNodes(std::vector< std::size_t > &&node_partition_ids)
void writeOtherMesh(std::string const &output_filename_base, std::vector< Partition > const &partitions, MeshLib::Properties const &partitioned_properties) const
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
std::size_t getNumberOfNodes() const
Get the number of nodes.
Definition Mesh.h:102
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
TCLAP::ValueArg< std::string > makeLogLevelArg()
void initOGSLogger(std::string const &log_level)
Definition Logging.cpp:64
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)
Definition of readMeshFromFile function.