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
122
123 const std::string input_file_name_wo_extension =
125 std::unique_ptr<MeshLib::Mesh> mesh_ptr(
127 INFO(
"Mesh '{:s}' read: {:d} nodes, {:d} elements.",
128 mesh_ptr->getName(),
129 mesh_ptr->getNumberOfNodes(),
130 mesh_ptr->getNumberOfElements());
131
133 output_directory_arg.getValue(),
135
136 if (ogs2metis_flag.getValue())
137 {
138 INFO(
"Write the mesh into METIS input file.");
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 {
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
175 if (exe_metis_flag.getValue())
176 {
177 INFO(
"METIS is running ...");
178 const std::string exe_name = argv[0];
180 INFO(
"Path to mpmetis is: \n\t{:s}", exe_path);
181
182 const std::string mpmetis_com =
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(
200 mesh_partitioner.mesh().getNumberOfNodes()));
201
202
203 if (exe_metis_flag.getValue())
204 {
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
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
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",
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}
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)
GITINFOLIB_EXPORT const std::string ogs_version
MeshLib::Mesh * readMeshFromFile(const std::string &file_name, bool const compute_element_neighbors)