swh:1:snp:6088ab52ef49920e01e3f334cdf4d5d6c8a822b9
Tip revision: c0085bf21f3cebbf8ca0cdaaea63905ddaec7933 authored by Lars Bilke on 08 March 2021, 19:43:41 UTC
Merge branch 'more-cpm' into 'master'
Merge branch 'more-cpm' into 'master'
Tip revision: c0085bf
GMSH2OGS.cpp
/**
* \file
* \author Thomas Fischer
* \date 2011-12-13
* \brief Implementation of the GMSH2OGS converter.
*
* \copyright
* Copyright (c) 2012-2021, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license
*
*/
// STL
#include <string>
#include <algorithm>
// ThirdParty
#include <tclap/CmdLine.h>
// BaseLib
#include "InfoLib/GitInfo.h"
#include "BaseLib/FileTools.h"
#include "BaseLib/RunTime.h"
#ifndef WIN32
#include "BaseLib/MemWatch.h"
#endif
#include "Applications/FileIO/Gmsh/GmshReader.h"
#include "GeoLib/AABB.h"
#include "MeshGeoToolsLib/IdentifySubdomainMesh.h"
#include "MeshGeoToolsLib/MeshNodeSearcher.h"
#include "MeshLib/IO/writeMeshToFile.h"
#include "MeshLib/Mesh.h"
#include "MeshLib/MeshEditing/DuplicateMeshComponents.h"
#include "MeshLib/MeshEditing/RemoveMeshComponents.h"
#include "MeshLib/MeshInformation.h"
#include "MeshLib/MeshQuality/MeshValidation.h"
#include "MeshLib/MeshSearch/ElementSearch.h"
static std::unique_ptr<MeshLib::Mesh> createMeshFromElements(
MeshLib::Mesh const& mesh,
std::vector<MeshLib::Element*> const& selected_elements,
std::string mesh_name)
{
// Create boundary mesh.
auto nodes = copyNodeVector(mesh.getNodes());
auto elements = copyElementVector(selected_elements, nodes);
// Cleanup unused nodes
removeMarkedNodes(markUnusedNodes(elements, nodes), nodes);
return std::make_unique<MeshLib::Mesh>(std::move(mesh_name), nodes,
elements);
}
static std::vector<std::unique_ptr<MeshLib::Mesh>> extractBoundaryMeshes(
MeshLib::Mesh const& mesh, std::vector<std::size_t> selected_element_ids)
{
// Bulk mesh node searcher usef for boundary mesh identification.
auto const& mesh_node_searcher =
MeshGeoToolsLib::MeshNodeSearcher::getMeshNodeSearcher(
mesh,
std::make_unique<MeshGeoToolsLib::SearchLength>(
0)); // Exact match of nodes.
auto const material_ids = materialIDs(mesh);
if (material_ids == nullptr)
{
OGS_FATAL(
"GMSH2OGS: Expected material ids to be present in the mesh to "
"extract boundary meshes.");
}
std::vector<std::unique_ptr<MeshLib::Mesh>> boundary_meshes;
auto const& elements = mesh.getElements();
while (!selected_element_ids.empty())
{
// Partition in two blocks, with elements for the material id at
// the end, s.t. one can erase them easily.
int const material_id = (*material_ids)[selected_element_ids.back()];
auto split = std::partition(
begin(selected_element_ids), end(selected_element_ids),
[&material_id, &material_ids](int const id) {
return (*material_ids)[id] != material_id;
});
// Add elements with same material id to the mesh.
std::vector<MeshLib::Element*> single_material_elements;
single_material_elements.reserve(
std::distance(split, end(selected_element_ids)));
std::transform(split, end(selected_element_ids),
std::back_inserter(single_material_elements),
[&](int const id) { return elements[id]; });
// Remove already extracted elements.
selected_element_ids.erase(split, end(selected_element_ids));
// Create boundary mesh and identify the nodes/elements.
boundary_meshes.push_back(createMeshFromElements(
mesh, single_material_elements, std::to_string(material_id)));
}
return boundary_meshes;
}
static void identifyAndWriteBoundaryMeshes(
MeshLib::Mesh const& mesh,
std::string const& file_name,
std::vector<std::unique_ptr<MeshLib::Mesh>>& boundary_meshes)
{
// Bulk mesh node searcher usef for boundary mesh identification.
auto const& mesh_node_searcher =
MeshGeoToolsLib::MeshNodeSearcher::getMeshNodeSearcher(
mesh,
std::make_unique<MeshGeoToolsLib::SearchLength>(
0)); // Exact match of nodes.
for (auto& boundary_mesh : boundary_meshes)
{
identifySubdomainMesh(*boundary_mesh, mesh, mesh_node_searcher);
// Save the boundary mesh.
auto boundary_mesh_file_name = BaseLib::dropFileExtension(file_name) +
'_' + boundary_mesh->getName() +
BaseLib::getFileExtension(file_name);
MeshLib::IO::writeMeshToFile(*boundary_mesh, boundary_mesh_file_name);
}
}
int main (int argc, char* argv[])
{
TCLAP::CmdLine cmd(
"Converting meshes in gmsh file format (ASCII, version 2.2) to a vtk "
"unstructured grid file (new OGS file format) or to the old OGS file "
"format - see options.\n\n"
"OpenGeoSys-6 software, version " +
GitInfoLib::GitInfo::ogs_version +
".\n"
"Copyright (c) 2012-2021, OpenGeoSys Community "
"(http://www.opengeosys.org)",
' ', GitInfoLib::GitInfo::ogs_version);
TCLAP::ValueArg<std::string> ogs_mesh_arg(
"o",
"out",
"filename for output mesh (if extension is .msh, old OGS-5 fileformat is written, if extension is .vtu, a vtk unstructure grid file is written (OGS-6 mesh format))",
true,
"",
"filename as string");
cmd.add(ogs_mesh_arg);
TCLAP::ValueArg<std::string> gmsh_mesh_arg(
"i",
"in",
"gmsh input file",
true,
"",
"filename as string");
cmd.add(gmsh_mesh_arg);
TCLAP::SwitchArg valid_arg("v", "validation", "validate the mesh");
cmd.add(valid_arg);
TCLAP::SwitchArg create_boundary_meshes_arg(
"b", "boundaries", "if set, boundary meshes will be generated");
cmd.add(create_boundary_meshes_arg);
TCLAP::SwitchArg exclude_lines_arg("e", "exclude-lines",
"if set, lines will not be written to the ogs mesh");
cmd.add(exclude_lines_arg);
cmd.parse(argc, argv);
// *** read mesh
INFO("Reading {:s}.", gmsh_mesh_arg.getValue());
#ifndef WIN32
BaseLib::MemWatch mem_watch;
unsigned long mem_without_mesh (mem_watch.getVirtMemUsage());
#endif
BaseLib::RunTime run_time;
run_time.start();
MeshLib::Mesh* mesh(
FileIO::GMSH::readGMSHMesh(gmsh_mesh_arg.getValue()));
if (mesh == nullptr) {
INFO("Could not read mesh from {:s}.", gmsh_mesh_arg.getValue());
return -1;
}
#ifndef WIN32
INFO("Mem for mesh: {} MiB",
(mem_watch.getVirtMemUsage() - mem_without_mesh) / (1024 * 1024));
#endif
INFO("Time for reading: {:f} seconds.", run_time.elapsed());
INFO("Read {:d} nodes and {:d} elements.", mesh->getNumberOfNodes(),
mesh->getNumberOfElements());
// Optionally remove line elements or create boundary meshes.
if (exclude_lines_arg.getValue() || create_boundary_meshes_arg.getValue())
{
auto ex = MeshLib::ElementSearch(*mesh);
ex.searchByElementType(MeshLib::MeshElemType::LINE);
auto const& selected_element_ids = ex.getSearchedElementIDs();
// First we extract the boundary meshes, then optionally remove the line
// elements, and only then run the node/element identification and write
// the meshes.
std::vector<std::unique_ptr<MeshLib::Mesh>> boundary_meshes;
if (create_boundary_meshes_arg.getValue())
{
boundary_meshes =
extractBoundaryMeshes(*mesh, selected_element_ids);
}
if (exclude_lines_arg.getValue())
{
auto m = MeshLib::removeElements(*mesh, selected_element_ids,
mesh->getName() + "-withoutLines");
if (m != nullptr)
{
INFO("Removed {:d} lines.",
mesh->getNumberOfElements() - m->getNumberOfElements());
std::swap(m, mesh);
delete m;
}
else
{
INFO("Mesh does not contain any lines.");
}
}
if (create_boundary_meshes_arg.getValue())
{
identifyAndWriteBoundaryMeshes(*mesh, ogs_mesh_arg.getValue(),
boundary_meshes);
}
}
// *** print meshinformation
INFO("Please check your mesh carefully!");
INFO(
"Degenerated or redundant mesh elements can cause OGS to stop or "
"misbehave.");
INFO("Use the -e option to delete redundant line elements.");
// Geometric information
const GeoLib::AABB aabb = MeshLib::MeshInformation::getBoundingBox(*mesh);
auto const minPt(aabb.getMinPoint());
auto const maxPt(aabb.getMaxPoint());
INFO("Node coordinates:");
INFO("\tx [{:g}, {:g}] (extent {:g})", minPt[0], maxPt[0],
maxPt[0] - minPt[0]);
INFO("\ty [{:g}, {:g}] (extent {:g})", minPt[1], maxPt[1],
maxPt[1] - minPt[1]);
INFO("\tz [{:g}, {:g}] (extent {:g})", minPt[2], maxPt[2],
maxPt[2] - minPt[2]);
INFO("Edge length: [{:g}, {:g}]", mesh->getMinEdgeLength(),
mesh->getMaxEdgeLength());
// Element information
MeshLib::MeshInformation::writeAllNumbersOfElementTypes(*mesh);
MeshLib::MeshInformation::writePropertyVectorInformation(*mesh);
if (valid_arg.isSet())
{
MeshLib::MeshInformation::writeMeshValidationResults(*mesh);
}
// *** write mesh in new format
MeshLib::IO::writeMeshToFile(*mesh, ogs_mesh_arg.getValue());
delete mesh;
}