Skip to content

Commit

Permalink
Merge pull request #233 from j8xixo12/gmsh_support
Browse files Browse the repository at this point in the history
add Gmsh mesh file parser
  • Loading branch information
yungyuc authored Jul 30, 2023
2 parents 9c32560 + becebae commit ecbffcc
Show file tree
Hide file tree
Showing 15 changed files with 953 additions and 0 deletions.
2 changes: 2 additions & 0 deletions cpp/modmesh/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ add_subdirectory(onedim)
add_subdirectory(python)
add_subdirectory(spacetime)
add_subdirectory(view)
add_subdirectory(inout)

set(MODMESH_ROOT_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/modmesh.hpp
Expand Down Expand Up @@ -80,6 +81,7 @@ set(MODMESH_TERMINAL_FILES
${MODMESH_ONEDIM_FILES}
${MODMESH_SPACETIME_FILES}
${MODMESH_PYTHON_FILES}
${MODMESH_INOUT_FILES}
CACHE FILEPATH "" FORCE)

set(MODMESH_GRAPHIC_FILES
Expand Down
28 changes: 28 additions & 0 deletions cpp/modmesh/inout/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@

cmake_minimum_required(VERSION 3.16)

set(MODMESH_INOUT_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/inout.hpp
${CMAKE_CURRENT_SOURCE_DIR}/gmsh.hpp
CACHE FILEPATH "" FORCE)

set(MODMESH_INOUT_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/gmsh.cpp
CACHE FILEPATH "" FORCE)

set(MODMESH_INOUT_PYMODHEADERS
${CMAKE_CURRENT_SOURCE_DIR}/pymod/inout_pymod.hpp
CACHE FILEPATH "" FORCE)

set(MODMESH_INOUT_PYMODSOURCES
${CMAKE_CURRENT_SOURCE_DIR}/pymod/inout_pymod.cpp
${CMAKE_CURRENT_SOURCE_DIR}/pymod/wrap_Gmsh.cpp
CACHE FILEPATH "" FORCE)

set(MODMESH_INOUT_FILES
${MODMESH_INOUT_HEADERS}
${MODMESH_INOUT_SOURCES}
${MODMESH_INOUT_PYMODHEADERS}
${MODMESH_INOUT_PYMODSOURCES}
CACHE FILEPATH "" FORCE)
# vim: set ff=unix fenc=utf8 nobomb et sw=4 ts=4 sts=4:
96 changes: 96 additions & 0 deletions cpp/modmesh/inout/gmsh.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#include <modmesh/inout/gmsh.hpp>
#ifdef _WIN32
#include <algorithm>
#endif // _WIN32
namespace modmesh
{
namespace inout
{
Gmsh::Gmsh(const std::string & data)
{
bool meta_enter = false;
bool node_enter = false;
bool element_enter = false;
// clang-format off
std::unordered_map<std::string, std::function<void()>> keyword_handler = {
{"$MeshFormat", [this, &meta_enter]() { load_meta(); meta_enter = true; }},
{"$Nodes", [this, &node_enter]() { load_nodes(); node_enter = true; }},
{"$Elements", [this, &element_enter]() { load_elements(); element_enter = true; }},
{"$PhysicalNames", [this]() { load_physical(); }}};
// clang-format on

// String stream on windows need to remove \r for keyword comparison.
// DOS file newline character is CRLF, std::getline default using LF as delimeter
// therefore string seperated by std::getline will contain \r, it will cause
// keyword compare failed.
// TODO: Keyword comparison can use regular expression.
#ifdef _WIN32
std::string data_copy = data;
data_copy.erase(std::remove(data_copy.begin(), data_copy.end(), '\r'), data_copy.end());
stream << data_copy;
#else // _WIN32
stream << data;
#endif // _WIN32

std::string line;
while (std::getline(stream, line))
{
// Using a finite state machine to check the input msh file format is valid or not.
// $ is a keyword to trigger state transition.
if (line.find('$') != std::string::npos)
{
auto it = keyword_handler.find(line);
if (it != keyword_handler.end())
{
if (is_valid_transition(it->first))
{
it->second();
}
else
{
break;
}
}
else
{
break;
}
}
}

// MeshFormat, Nodes and Elements section is mandatory in gmsh msh file,
// therefore need to check these sections are exist or not otherwise
// modmesh may crash during mesh processing.
if (!(meta_enter && node_enter && element_enter))
{
throw std::invalid_argument("Incorrect msh file format.");
}
}

std::shared_ptr<StaticMesh> Gmsh::to_block()
{
std::shared_ptr<StaticMesh> block = StaticMesh::construct(m_eldim.max(), m_nds.shape(0), 0, m_elems.size());
build_interior(block);
return block;
}

void Gmsh::build_interior(const std::shared_ptr<StaticMesh> & blk)
{
blk->cltpn().swap(m_cltpn);
blk->ndcrd().swap(m_nds);
for (size_t i = 0; i < m_elems.size(); ++i)
{
blk->clnds()(i, 0) = m_elems[i][0];
for (size_t j = 1; j <= m_elems[i][0]; ++j)
{
blk->clnds()(i, j) = m_elems[i][j];
}
}
blk->build_interior(true);
blk->build_boundary();
blk->build_ghost();
}
} /* end namespace inout */
} /* end namespace modmesh */

// vim: set ff=unix fenc=utf8 et sw=4 ts=4 sts=4:
Loading

0 comments on commit ecbffcc

Please sign in to comment.