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
98
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
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 const auto output_directory = output_directory_arg.getValue();
120
125
126 const std::string input_file_name_wo_extension =
128 std::unique_ptr<MeshLib::Mesh> mesh_ptr(
130 INFO(
"Mesh '{:s}' read: {:d} nodes, {:d} elements.",
131 mesh_ptr->getName(),
132 mesh_ptr->getNumberOfNodes(),
133 mesh_ptr->getNumberOfElements());
134
136 output_directory,
138
139 if (ogs2metis_flag.getValue())
140 {
141 INFO(
"Write the mesh into METIS input file.");
143 output_file_name_wo_extension + ".mesh");
144 INFO(
"Total runtime: {:g} s.", run_timer.
elapsed());
145 INFO(
"Total CPU time: {:g} s.", CPU_timer.
elapsed());
146
147#ifdef USE_PETSC
148 MPI_Finalize();
149#endif
150 return EXIT_SUCCESS;
151 }
152
154 nparts.getValue(), std::move(mesh_ptr));
155
156 const int num_partitions = nparts.getValue();
157
158 if (num_partitions < 1)
159 {
160 OGS_FATAL(
"Number of partitions must be positive.");
161 }
162
163 if (num_partitions == 1)
164 {
166 "Partitioning the mesh into one domain is unnecessary because OGS "
167 "reads vtu mesh data directly when called with 'mpirun bin/ogs "
168 "-np=1'.");
169 }
170
171 auto metis_mesh = output_file_name_wo_extension;
172 if (metis_mesh_input.getValue() != "")
173 {
174 metis_mesh = metis_mesh_input.getValue();
175 }
176
177
178 if (exe_metis_flag.getValue())
179 {
180 INFO(
"METIS is running ...");
181 const std::string exe_name = argv[0];
183 INFO(
"Path to mpmetis is: \n\t{:s}", exe_path);
184
185 const std::string mpmetis_com =
187 metis_mesh + ".mesh" + "\" " + std::to_string(nparts.getValue());
188
189 INFO(
"Running: {:s}", mpmetis_com);
190 const int status = system(mpmetis_com.c_str());
191 if (status != 0)
192 {
193 INFO(
"Failed in system calling.");
194 INFO(
"Return value of system call {:d} ", status);
195#ifdef USE_PETSC
196 MPI_Finalize();
197#endif
198 return EXIT_FAILURE;
199 }
200 }
201 mesh_partitioner.resetPartitionIdsForNodes(
203 mesh_partitioner.mesh().getNumberOfNodes()));
204
205
206 if (exe_metis_flag.getValue())
207 {
209 }
210
211 INFO(
"Partitioning the mesh in the node wise way ...");
212 mesh_partitioner.partitionByMETIS();
213
214 INFO(
"Partitioning other meshes according to the main mesh partitions.");
215 for (auto const& filename : other_meshes_filenames_arg.getValue())
216 {
217 std::unique_ptr<MeshLib::Mesh> mesh(
219 INFO(
"Mesh '{:s}' from file '{:s}' read: {:d} nodes, {:d} elements.",
220 mesh->getName(), filename, mesh->getNumberOfNodes(),
221 mesh->getNumberOfElements());
222
223 std::string const other_mesh_output_file_name_wo_extension =
225 output_directory,
227 auto partitions = mesh_partitioner.partitionOtherMesh(*mesh);
228
230 mesh_partitioner.renumberBulkIdsProperty(partitions,
231 partitioned_properties);
232
233 mesh_partitioner.writeOtherMesh(
234 other_mesh_output_file_name_wo_extension, partitions,
235 partitioned_properties);
236 }
237
239 io_run_timer.
start();
240 mesh_partitioner.write(output_file_name_wo_extension);
241 INFO(
"Writing the partitions data into binary files took {:g} s",
243
244 INFO(
"Total runtime: {:g} s.", run_timer.
elapsed());
245 INFO(
"Total CPU time: {:g} s.", CPU_timer.
elapsed());
246
247#ifdef USE_PETSC
248 MPI_Finalize();
249#endif
250 return EXIT_SUCCESS;
251}
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
void start()
Start the timer.
double elapsed() const
Get the elapsed time after started.
double elapsed() const
Get the elapsed time in seconds.
void start()
Start the timer.
void writeMETIS(std::vector< MeshLib::Element * > const &elements, const std::string &file_name)
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)
std::vector< std::size_t > readMetisData(const std::string &file_name_base, long const number_of_partitions, std::size_t const number_of_nodes)
void setConsoleLogLevel(std::string const &level_string)
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)