OGS
GMSH2OGS.cpp
Go to the documentation of this file.
1 
15 // STL
16 #include <algorithm>
17 #include <string>
18 
19 // ThirdParty
20 #include <tclap/CmdLine.h>
21 
22 // BaseLib
23 #include "BaseLib/FileTools.h"
24 #include "BaseLib/RunTime.h"
25 #include "InfoLib/GitInfo.h"
26 #ifndef WIN32
27 #include "BaseLib/MemWatch.h"
28 #endif
29 
31 #include "GeoLib/AABB.h"
35 #include "MeshLib/Mesh.h"
41 
42 static std::unique_ptr<MeshLib::Mesh> createMeshFromElements(
43  MeshLib::Mesh const& mesh,
44  std::vector<MeshLib::Element*> const& selected_elements,
45  std::string mesh_name)
46 {
47  // Create boundary mesh.
48  auto nodes = copyNodeVector(mesh.getNodes());
49  auto elements = copyElementVector(selected_elements, nodes);
50 
51  // Cleanup unused nodes
52  removeMarkedNodes(markUnusedNodes(elements, nodes), nodes);
53 
54  return std::make_unique<MeshLib::Mesh>(std::move(mesh_name), nodes,
55  elements);
56 }
57 
58 static std::vector<std::unique_ptr<MeshLib::Mesh>> extractBoundaryMeshes(
59  MeshLib::Mesh const& mesh, std::vector<std::size_t> selected_element_ids)
60 {
61  auto const material_ids = materialIDs(mesh);
62  if (material_ids == nullptr)
63  {
64  OGS_FATAL(
65  "GMSH2OGS: Expected material ids to be present in the mesh to "
66  "extract boundary meshes.");
67  }
68 
69  std::vector<std::unique_ptr<MeshLib::Mesh>> boundary_meshes;
70 
71  auto const& elements = mesh.getElements();
72 
73  while (!selected_element_ids.empty())
74  {
75  // Partition in two blocks, with elements for the material id at
76  // the end, s.t. one can erase them easily.
77  int const material_id = (*material_ids)[selected_element_ids.back()];
78  auto split = std::partition(
79  begin(selected_element_ids), end(selected_element_ids),
80  [&material_id, &material_ids](int const id)
81  { return (*material_ids)[id] != material_id; });
82 
83  // Add elements with same material id to the mesh.
84  std::vector<MeshLib::Element*> single_material_elements;
85  single_material_elements.reserve(
86  std::distance(split, end(selected_element_ids)));
87  std::transform(split, end(selected_element_ids),
88  std::back_inserter(single_material_elements),
89  [&](int const id) { return elements[id]; });
90 
91  // Remove already extracted elements.
92  selected_element_ids.erase(split, end(selected_element_ids));
93 
94  // Create boundary mesh and identify the nodes/elements.
95  boundary_meshes.push_back(createMeshFromElements(
96  mesh, single_material_elements, std::to_string(material_id)));
97  }
98  return boundary_meshes;
99 }
100 
102  MeshLib::Mesh const& mesh,
103  std::string const& file_name,
104  std::vector<std::unique_ptr<MeshLib::Mesh>>& boundary_meshes)
105 {
106  // Bulk mesh node searcher usef for boundary mesh identification.
107  auto const& mesh_node_searcher =
109  mesh,
110  std::make_unique<MeshGeoToolsLib::SearchLength>(
111  0)); // Exact match of nodes.
112 
113  for (auto& boundary_mesh : boundary_meshes)
114  {
115  identifySubdomainMesh(*boundary_mesh, mesh, mesh_node_searcher);
116 
117  // Save the boundary mesh.
118  auto boundary_mesh_file_name = BaseLib::dropFileExtension(file_name) +
119  '_' + boundary_mesh->getName() +
120  BaseLib::getFileExtension(file_name);
121 
122  MeshLib::IO::writeMeshToFile(*boundary_mesh, boundary_mesh_file_name);
123  }
124 }
125 
126 int main(int argc, char* argv[])
127 {
128  TCLAP::CmdLine cmd(
129  "Converting meshes in gmsh file format (ASCII, version 2.2) to a vtk "
130  "unstructured grid file (new OGS file format) or to the old OGS file "
131  "format - see options.\n\n"
132  "OpenGeoSys-6 software, version " +
134  ".\n"
135  "Copyright (c) 2012-2022, OpenGeoSys Community "
136  "(http://www.opengeosys.org)",
138 
139  TCLAP::ValueArg<std::string> ogs_mesh_arg(
140  "o",
141  "out",
142  "filename for output mesh (if extension is .msh, old OGS-5 fileformat "
143  "is written, if extension is .vtu, a vtk unstructure grid file is "
144  "written (OGS-6 mesh format))",
145  true,
146  "",
147  "filename as string");
148  cmd.add(ogs_mesh_arg);
149 
150  TCLAP::ValueArg<std::string> gmsh_mesh_arg("i", "in", "gmsh input file",
151  true, "", "filename as string");
152  cmd.add(gmsh_mesh_arg);
153 
154  TCLAP::SwitchArg valid_arg("v", "validation", "validate the mesh");
155  cmd.add(valid_arg);
156 
157  TCLAP::SwitchArg create_boundary_meshes_arg(
158  "b", "boundaries", "if set, boundary meshes will be generated");
159  cmd.add(create_boundary_meshes_arg);
160 
161  TCLAP::SwitchArg exclude_lines_arg(
162  "e", "exclude-lines",
163  "if set, lines will not be written to the ogs mesh");
164  cmd.add(exclude_lines_arg);
165 
166  cmd.parse(argc, argv);
167 
168  // *** read mesh
169  INFO("Reading {:s}.", gmsh_mesh_arg.getValue());
170 #ifndef WIN32
171  BaseLib::MemWatch mem_watch;
172  unsigned long mem_without_mesh(mem_watch.getVirtMemUsage());
173 #endif
174  BaseLib::RunTime run_time;
175  run_time.start();
176  MeshLib::Mesh* mesh(FileIO::GMSH::readGMSHMesh(gmsh_mesh_arg.getValue()));
177 
178  if (mesh == nullptr)
179  {
180  INFO("Could not read mesh from {:s}.", gmsh_mesh_arg.getValue());
181  return -1;
182  }
183 #ifndef WIN32
184  INFO("Mem for mesh: {} MiB",
185  (mem_watch.getVirtMemUsage() - mem_without_mesh) / (1024 * 1024));
186 #endif
187 
188  INFO("Time for reading: {:f} seconds.", run_time.elapsed());
189  INFO("Read {:d} nodes and {:d} elements.", mesh->getNumberOfNodes(),
190  mesh->getNumberOfElements());
191 
192  // Optionally remove line elements or create boundary meshes.
193  if (exclude_lines_arg.getValue() || create_boundary_meshes_arg.getValue())
194  {
195  auto ex = MeshLib::ElementSearch(*mesh);
196  ex.searchByElementType(MeshLib::MeshElemType::LINE);
197  auto const& selected_element_ids = ex.getSearchedElementIDs();
198 
199  // First we extract the boundary meshes, then optionally remove the line
200  // elements, and only then run the node/element identification and write
201  // the meshes.
202 
203  std::vector<std::unique_ptr<MeshLib::Mesh>> boundary_meshes;
204  if (create_boundary_meshes_arg.getValue())
205  {
206  boundary_meshes =
207  extractBoundaryMeshes(*mesh, selected_element_ids);
208  }
209 
210  if (exclude_lines_arg.getValue())
211  {
212  auto m = MeshLib::removeElements(*mesh, selected_element_ids,
213  mesh->getName() + "-withoutLines");
214  if (m != nullptr)
215  {
216  INFO("Removed {:d} lines.",
217  mesh->getNumberOfElements() - m->getNumberOfElements());
218  std::swap(m, mesh);
219  delete m;
220  }
221  else
222  {
223  INFO("Mesh does not contain any lines.");
224  }
225  }
226 
227  if (create_boundary_meshes_arg.getValue())
228  {
229  identifyAndWriteBoundaryMeshes(*mesh, ogs_mesh_arg.getValue(),
230  boundary_meshes);
231  }
232  }
233  // *** print meshinformation
234 
235  INFO("Please check your mesh carefully!");
236  INFO(
237  "Degenerated or redundant mesh elements can cause OGS to stop or "
238  "misbehave.");
239  INFO("Use the -e option to delete redundant line elements.");
240 
241  // Geometric information
243  auto const minPt(aabb.getMinPoint());
244  auto const maxPt(aabb.getMaxPoint());
245  INFO("Node coordinates:");
246  INFO("\tx [{:g}, {:g}] (extent {:g})", minPt[0], maxPt[0],
247  maxPt[0] - minPt[0]);
248  INFO("\ty [{:g}, {:g}] (extent {:g})", minPt[1], maxPt[1],
249  maxPt[1] - minPt[1]);
250  INFO("\tz [{:g}, {:g}] (extent {:g})", minPt[2], maxPt[2],
251  maxPt[2] - minPt[2]);
252 
253  INFO("Edge length: [{:g}, {:g}]", mesh->getMinEdgeLength(),
254  mesh->getMaxEdgeLength());
255 
256  // Element information
258 
260 
261  if (valid_arg.isSet())
262  {
264  }
265 
266  // *** write mesh in new format
267  MeshLib::IO::writeMeshToFile(*mesh, ogs_mesh_arg.getValue());
268 
269  delete mesh;
270 }
Definition of the AABB class.
Definition of Duplicate functions.
#define OGS_FATAL(...)
Definition: Error.h:26
Filename manipulation routines.
int main(int argc, char *argv[])
Definition: GMSH2OGS.cpp:126
static std::vector< std::unique_ptr< MeshLib::Mesh > > extractBoundaryMeshes(MeshLib::Mesh const &mesh, std::vector< std::size_t > selected_element_ids)
Definition: GMSH2OGS.cpp:58
static std::unique_ptr< MeshLib::Mesh > createMeshFromElements(MeshLib::Mesh const &mesh, std::vector< MeshLib::Element * > const &selected_elements, std::string mesh_name)
Definition: GMSH2OGS.cpp:42
static void identifyAndWriteBoundaryMeshes(MeshLib::Mesh const &mesh, std::string const &file_name, std::vector< std::unique_ptr< MeshLib::Mesh >> &boundary_meshes)
Definition: GMSH2OGS.cpp:101
Git information.
void INFO(char const *fmt, Args const &... args)
Definition: Logging.h:32
Definition of the MemWatch class.
Definition of the MeshInformation class.
Definition of the MeshValidation class.
Definition of the Mesh class.
Definition of the RunTime class.
unsigned long getVirtMemUsage()
Definition: MemWatch.cpp:59
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
Class AABB is an axis aligned bounding box around a given set of geometric points of (template) type ...
Definition: AABB.h:49
Eigen::Vector3d const & getMinPoint() const
Definition: AABB.h:172
Eigen::Vector3d const & getMaxPoint() const
Definition: AABB.h:179
static MeshNodeSearcher const & getMeshNodeSearcher(MeshLib::Mesh const &mesh, std::unique_ptr< MeshGeoToolsLib::SearchLength > &&search_length_algorithm)
Element search class.
Definition: ElementSearch.h:28
static void writePropertyVectorInformation(const MeshLib::Mesh &mesh)
writes out property vector information
static GeoLib::AABB getBoundingBox(const MeshLib::Mesh &mesh)
Returns the bounding box of the mesh.
static void writeMeshValidationResults(MeshLib::Mesh &mesh)
static void writeAllNumbersOfElementTypes(const MeshLib::Mesh &mesh)
writes all numbers of element types
double getMaxEdgeLength() const
Get the maximum edge length over all elements of the mesh.
Definition: Mesh.h:83
std::vector< Node * > const & getNodes() const
Get the nodes-vector for the mesh.
Definition: Mesh.h:95
double getMinEdgeLength() const
Get the minimum edge length over all elements of the mesh.
Definition: Mesh.h:80
std::vector< Element * > const & getElements() const
Get the element-vector for the mesh.
Definition: Mesh.h:98
const std::string getName() const
Get name of the mesh.
Definition: Mesh.h:92
std::size_t getNumberOfNodes() const
Get the number of nodes.
Definition: Mesh.h:89
std::size_t getNumberOfElements() const
Get the number of elements.
Definition: Mesh.h:86
std::string getFileExtension(const std::string &path)
Definition: FileTools.cpp:186
std::string dropFileExtension(std::string const &filename)
Definition: FileTools.cpp:169
MeshLib::Mesh * readGMSHMesh(std::string const &fname)
Definition: GmshReader.cpp:270
GITINFOLIB_EXPORT const std::string ogs_version
void identifySubdomainMesh(MeshLib::Mesh &subdomain_mesh, MeshLib::Mesh const &bulk_mesh, MeshNodeSearcher const &mesh_node_searcher, bool const force_overwrite=false)
int writeMeshToFile(const MeshLib::Mesh &mesh, std::filesystem::path const &file_path, [[maybe_unused]] std::set< std::string > variable_output_names)
MeshLib::Mesh * removeElements(const MeshLib::Mesh &mesh, const std::vector< std::size_t > &removed_element_ids, const std::string &new_mesh_name)
std::vector< Node * > copyNodeVector(const std::vector< Node * > &nodes)
Creates a deep copy of a Node vector.
PropertyVector< int > const * materialIDs(Mesh const &mesh)
Definition: Mesh.cpp:258
std::vector< bool > markUnusedNodes(std::vector< Element * > const &elements, std::vector< Node * > const &nodes)
Marks nodes not used by any of the elements.
void removeMarkedNodes(std::vector< bool > const &nodes_to_delete, std::vector< Node * > &nodes)
Deallocates and removes nodes marked true.
std::vector< Element * > copyElementVector(std::vector< Element * > const &elements, std::vector< Node * > const &new_nodes, std::vector< std::size_t > const *const node_id_map)