OGS
PartitionMesh.cpp
Go to the documentation of this file.
1 
15 #include <spdlog/spdlog.h>
16 #include <tclap/CmdLine.h>
17 
18 #include "BaseLib/CPUTime.h"
19 #include "BaseLib/FileTools.h"
20 #include "BaseLib/RunTime.h"
21 #include "InfoLib/GitInfo.h"
23 #include "Metis.h"
25 
26 using namespace ApplicationUtils;
27 
28 int main(int argc, char* argv[])
29 {
30  TCLAP::CmdLine cmd(
31  "Partition a mesh for parallel computing."
32  "The tasks of this tool are in twofold:\n"
33  "1. Convert mesh file to the input file of the partitioning tool,\n"
34  "2. Partition a mesh using the partitioning tool,\n"
35  "\tcreate the mesh data of each partition,\n"
36  "\trenumber the node indices of each partition,\n"
37  "\tand output the results for parallel computing.\n"
38  "Note: If this tool is installed as a system command,\n"
39  "\tthe command must be run with its full path.\n\n"
40  "OpenGeoSys-6 software, version " +
42  ".\n"
43  "Copyright (c) 2012-2021, OpenGeoSys Community "
44  "(http://www.opengeosys.org)",
46  TCLAP::ValueArg<std::string> mesh_input(
47  "i", "mesh-input-file",
48  "the name of the file containing the input mesh", true, "",
49  "file name of input mesh");
50  cmd.add(mesh_input);
51 
52  TCLAP::ValueArg<std::string> metis_mesh_input(
53  "x", "metis-mesh-input-file",
54  "base name (without .mesh extension) of the file containing the metis "
55  "input mesh",
56  false, "",
57  "base name (without .mesh extension) of the file containing the metis "
58  "input mesh");
59  cmd.add(metis_mesh_input);
60 
61  TCLAP::ValueArg<std::string> output_directory_arg(
62  "o", "output", "directory name for the output files", false, "",
63  "directory");
64  cmd.add(output_directory_arg);
65 
66  TCLAP::ValueArg<int> nparts("n", "np", "the number of partitions", false, 2,
67  "integer");
68  cmd.add(nparts);
69 
70  TCLAP::SwitchArg ogs2metis_flag(
71  "s", "ogs2metis",
72  "Indicator to convert the ogs mesh file to METIS input file", cmd,
73  false);
74 
75  TCLAP::SwitchArg exe_metis_flag(
76  "m", "exe_metis", "Call mpmetis inside the programme via system().",
77  false);
78  cmd.add(exe_metis_flag);
79 
80  TCLAP::SwitchArg lh_elems_flag(
81  "q", "lh_elements", "Mixed linear and high order elements.", false);
82  cmd.add(lh_elems_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  BaseLib::setConsoleLogLevel(log_level_arg.getValue());
106  spdlog::set_pattern("%^%l:%$ %v");
107  spdlog::set_error_handler(
108  [](const std::string& msg)
109  {
110  std::cerr << "spdlog error: " << msg << std::endl;
111  OGS_FATAL("spdlog logger error occurred.");
112  });
113 
114  BaseLib::RunTime run_timer;
115  run_timer.start();
116  BaseLib::CPUTime CPU_timer;
117  CPU_timer.start();
118 
119  const std::string input_file_name_wo_extension =
120  BaseLib::dropFileExtension(mesh_input.getValue());
121  std::unique_ptr<MeshLib::Mesh> mesh_ptr(
122  MeshLib::IO::readMeshFromFile(input_file_name_wo_extension + ".vtu"));
123  INFO("Mesh '{:s}' read: {:d} nodes, {:d} elements.",
124  mesh_ptr->getName(),
125  mesh_ptr->getNumberOfNodes(),
126  mesh_ptr->getNumberOfElements());
127 
128  std::string const output_file_name_wo_extension = BaseLib::joinPaths(
129  output_directory_arg.getValue(),
130  BaseLib::extractBaseNameWithoutExtension(mesh_input.getValue()));
131 
132  if (ogs2metis_flag.getValue())
133  {
134  INFO("Write the mesh into METIS input file.");
135  ApplicationUtils::writeMETIS(mesh_ptr->getElements(),
136  output_file_name_wo_extension + ".mesh");
137  INFO("Total runtime: {:g} s.", run_timer.elapsed());
138  INFO("Total CPU time: {:g} s.", CPU_timer.elapsed());
139 
140  return EXIT_SUCCESS;
141  }
142 
144  nparts.getValue(), std::move(mesh_ptr));
145 
146  const int num_partitions = nparts.getValue();
147 
148  if (num_partitions < 1)
149  {
150  OGS_FATAL("Number of partitions must be positive.");
151  }
152 
153  if (num_partitions == 1)
154  {
155  OGS_FATAL(
156  "Partitioning the mesh into one domain is unnecessary because OGS "
157  "reads vtu mesh data directly when called with 'mpirun bin/ogs "
158  "-np=1'.");
159  }
160 
161  auto metis_mesh = output_file_name_wo_extension;
162  if (metis_mesh_input.getValue() != "")
163  {
164  metis_mesh = metis_mesh_input.getValue();
165  }
166 
167  // Execute mpmetis via system(...)
168  if (exe_metis_flag.getValue())
169  {
170  INFO("METIS is running ...");
171  const std::string exe_name = argv[0];
172  const std::string exe_path = BaseLib::extractPath(exe_name);
173  INFO("Path to mpmetis is: \n\t{:s}", exe_path);
174 
175  const std::string mpmetis_com =
176  BaseLib::joinPaths(exe_path, "mpmetis") + " -gtype=nodal " + "'" +
177  metis_mesh + ".mesh" + "' " + std::to_string(nparts.getValue());
178 
179  INFO("Running: {:s}", mpmetis_com);
180  const int status = system(mpmetis_com.c_str());
181  if (status != 0)
182  {
183  INFO("Failed in system calling.");
184  INFO("Return value of system call {:d} ", status);
185  return EXIT_FAILURE;
186  }
187  }
188  mesh_partitioner.resetPartitionIdsForNodes(
189  readMetisData(metis_mesh, num_partitions,
190  mesh_partitioner.mesh().getNumberOfNodes()));
191 
192  // Remove metis partitioning files only if metis was run internally.
193  if (exe_metis_flag.getValue())
194  {
195  removeMetisPartitioningFiles(metis_mesh, num_partitions);
196  }
197 
198  INFO("Partitioning the mesh in the node wise way ...");
199  bool const is_mixed_high_order_linear_elems = lh_elems_flag.getValue();
200  mesh_partitioner.partitionByMETIS(is_mixed_high_order_linear_elems);
201 
202  INFO("Partitioning other meshes according to the main mesh partitions.");
203  for (auto const& filename : other_meshes_filenames_arg.getValue())
204  {
205  std::unique_ptr<MeshLib::Mesh> mesh(
207  INFO("Mesh '{:s}' from file '{:s}' read: {:d} nodes, {:d} elements.",
208  mesh->getName(), filename, mesh->getNumberOfNodes(),
209  mesh->getNumberOfElements());
210 
211  std::string const other_mesh_output_file_name_wo_extension =
213  output_directory_arg.getValue(),
215  auto const partitions = mesh_partitioner.partitionOtherMesh(
216  *mesh, is_mixed_high_order_linear_elems);
217 
218  auto partitioned_properties =
219  partitionProperties(mesh->getProperties(), partitions);
220  mesh_partitioner.renumberBulkNodeIdsProperty(
221  partitioned_properties.getPropertyVector<std::size_t>(
222  "bulk_node_ids", MeshLib::MeshItemType::Node, 1),
223  partitions);
224  mesh_partitioner.renumberBulkElementIdsProperty(
225  partitioned_properties.getPropertyVector<std::size_t>(
226  "bulk_element_ids", MeshLib::MeshItemType::Cell, 1),
227  partitions);
228  mesh_partitioner.writeOtherMesh(
229  other_mesh_output_file_name_wo_extension, partitions,
230  partitioned_properties);
231  }
232 
233  INFO("Write the data of partitions into binary files ...");
234  mesh_partitioner.write(output_file_name_wo_extension);
235 
236  INFO("Total runtime: {:g} s.", run_timer.elapsed());
237  INFO("Total CPU time: {:g} s.", CPU_timer.elapsed());
238 
239  return EXIT_SUCCESS;
240 }
Definition of the CPUTime class.
#define OGS_FATAL(...)
Definition: Error.h:26
Filename manipulation routines.
Git information.
void INFO(char const *fmt, Args const &... args)
Definition: Logging.h:32
Declare a class to perform node wise mesh partitioning.
int main(int argc, char *argv[])
Definition of the RunTime class.
void renumberBulkElementIdsProperty(MeshLib::PropertyVector< std::size_t > *const bulk_element_ids_pv, std::vector< Partition > const &local_partitions) const
void partitionByMETIS(const bool is_mixed_high_order_linear_elems)
void write(const std::string &file_name_base)
void renumberBulkNodeIdsProperty(MeshLib::PropertyVector< std::size_t > *const bulk_node_ids, std::vector< Partition > const &local_partitions) const
std::vector< Partition > partitionOtherMesh(MeshLib::Mesh const &mesh, bool const is_mixed_high_order_linear_elems) const
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
void start()
Start the timer.
Definition: RunTime.h:32
std::size_t getNumberOfNodes() const
Get the number of nodes.
Definition: Mesh.h:89
void writeMETIS(std::vector< MeshLib::Element * > const &elements, const std::string &file_name)
Definition: Metis.cpp:19
MeshLib::Properties partitionProperties(MeshLib::Properties const &properties, std::vector< Partition > const &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:34
std::string extractPath(std::string const &pathname)
Definition: FileTools.cpp:207
std::string extractBaseNameWithoutExtension(std::string const &pathname)
Definition: FileTools.cpp:180
std::string dropFileExtension(std::string const &filename)
Definition: FileTools.cpp:169
std::string joinPaths(std::string const &pathA, std::string const &pathB)
Definition: FileTools.cpp:212
GITINFOLIB_EXPORT const std::string ogs_version
MeshLib::Mesh * readMeshFromFile(const std::string &file_name)
Definition of readMeshFromFile function.