Skip to main content

gmshparser is a lightweight, 100 % tested and well documented package that parses Gmsh ascii file format (.msh)

Project description

gmshparser - parse Gmsh .msh file format

Python CI codecov PyPI - Version PyPI - Downloads Documentation Python Version License

gmshparser hero image

Package author: Jukka Aho (@ahojukka5)

Gmshparser is a small Python package which aims to do only one thing: parse Gmsh mesh file format. Package does not have any external dependencies to other packages and it aims to be a simple stand-alone solution for a common problem: how to import mesh to your favourite research FEM code?

Supported Gmsh MSH file formats

gmshparser supports multiple versions of the Gmsh MSH file format:

  • MSH 1.0: Legacy format using $NOD/$ENDNOD and $ELM/$ENDELM sections
  • MSH 2.0, 2.1, 2.2: Standard format with $MeshFormat, $Nodes, and $Elements sections
  • MSH 4.0, 4.1: Modern format with entity-based organization using $Entities section

The parser automatically detects the file format version and uses the appropriate parser for that version, so you don't need to worry about which version you're working with.

Installing package

To install the most recent package from Python Package Index (PyPi), use git:

pip install gmshparser

To install the development version, you can install the package directly from the GitHub:

pip install git+git://github.com/ahojukka5/gmshparser.git

Using application programming interface

To read mesh into Mesh object, use command parse. It takes a filename and parses the file with the set of parsers, defined in DEFAULT_PARSERS (see developing package section for more info..!)

import gmshparser
mesh = gmshparser.parse("data/testmesh.msh")
print(mesh)
Mesh name: data/testmesh.msh
Mesh version: 4.1
Number of nodes: 6
Minimum node tag: 1
Maximum node tag: 6
Number of node entities: 1
Number of elements: 2
Minimum element tag: 1
Maximum element tag: 2
Number of element entities: 1

After reading the model, you can querying your data form mesh object. For example, to extract all nodes from the model:

for entity in mesh.get_node_entities():
    for node in entity.get_nodes():
        nid = node.get_tag()
        ncoords = node.get_coordinates()
        print("Node id = %s, node coordinates = %s" % (nid, ncoords))
Node id = 1, node coordinates = (0.0, 0.0, 0.0)
Node id = 2, node coordinates = (1.0, 0.0, 0.0)
Node id = 3, node coordinates = (1.0, 1.0, 0.0)
Node id = 4, node coordinates = (0.0, 1.0, 0.0)
Node id = 5, node coordinates = (2.0, 0.0, 0.0)
Node id = 6, node coordinates = (2.0, 1.0, 0.0)

Extract all elements from the model:

for entity in mesh.get_element_entities():
    eltype = entity.get_element_type()
    print("Element type: %s" % eltype)
    for element in entity.get_elements():
        elid = element.get_tag()
        elcon = element.get_connectivity()
        print("Element id = %s, connectivity = %s" % (elid, elcon))
Element type: 3
Element id = 1, connectivity = [1, 2, 3, 4]
Element id = 2, connectivity = [2, 5, 6, 3]

If you are writing your FEM stuff with Python, then you have access to the all relevant properties of the model using mesh object. For further information on how to access nodes, elements, physical groups, and other things what Gmsh provides, take a look of documentation.

Using command line interface

gmshparser can also be useful even if you don't make FEM code in Python. The above loops used to extract nodes and elements are actually so common, that you can use them from the command line. This way you can print nodes and elements in a simpler format with command-line tools, making it easier to read an element mesh with C ++ or Fortran, for example. To extract nodes:

jukka@jukka-XPS-13-9380:~$ gmshparser data/testmesh.msh nodes
6
1 0.000000 0.000000 0.000000
2 1.000000 0.000000 0.000000
3 1.000000 1.000000 0.000000
4 0.000000 1.000000 0.000000
5 2.000000 0.000000 0.000000
6 2.000000 1.000000 0.000000

To extract elements, use choice elements. The first line is having the total number of elements, and the rest of the lines are in format element_id element_type element_connectivity. The length of the line naturally depends on how many nodes the element is having.

jukka@jukka-XPS-13-9380:~$ gmshparser data/testmesh.msh elements
2
1 3 1 2 3 4
2 3 2 5 6 3

Visualizing meshes using gmshparser and matplotlib

The intention of the package is not to visualize meshes. But as it is a quite common task to visualize 2-dimensional triangluar meshes in acedemic papers, lecture notes, and things like that, it can be done easily using gmshparser and matplotlib. There's a helper function gmshparser.helpers.get_triangles, which returns a tuple (X, Y, T) which can then be passed to matplotlib to get a mesh plot:

import gmshparser
mesh = gmshparser.parse("data/example_mesh.msh")
X, Y, T = gmshparser.helpers.get_triangles(mesh)

import matplotlib.pylab as plt
plt.figure()
plt.triplot(X, Y, T, color='black')
plt.axis('equal')
plt.axis('off')
plt.tight_layout()
plt.savefig('docs/example_mesh.svg')

Example mesh visualization

Developing package

gmshparser is written such a way, that it's easy to define your own parsers which are responsible for parsing some section, starting with $SectionName and ending with $EndSectionName. For example, a parser which is responsible to parse MeshFormat setion is MainFormatParser and it is defined with the following code:

class MeshFormatParser(AbstractParser):

    @staticmethod
    def get_section_name():
        return "$MeshFormat"

    @staticmethod
    def parse(mesh: Mesh, io: TextIO) -> None:
        s = io.readline().strip().split(" ")
        mesh.set_version(float(s[0]))
        mesh.set_ascii(int(s[1]) == 0)
        mesh.set_precision(int(s[2]))

All the active parsers used in parsing are then appended to the list of parsers in MainParser, from where they are called when an appropriate get_section_name() is found from file considered to be parsed. The MainParser itself is then called in parse to get things done:

def parse(filename: str) -> Mesh:
    """Parse Gmsh .msh file and return `Mesh` object."""
    mesh = Mesh()
    mesh.set_name(filename)
    parser = MainParser()
    with open(filename, "r") as io:
        parser.parse(mesh, io)
    return mesh

If you want to learn how to write your own parser, you can e.g. take of look of NodesParser which is responsible for parsing nodes and ElementsParser which is responsible for parsing elements, to get an idea how things are implemented.

Contributing to project

Like in all other open source projects, contributions are always welcome to this project too! If you have some great ideas how to make this package better, feature requests etc., you can open an issue on gmshparser's issue tracker or contact me (ahojukka5@gmail.com) directly.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gmshparser-0.3.1.tar.gz (17.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gmshparser-0.3.1-py3-none-any.whl (22.3 kB view details)

Uploaded Python 3

File details

Details for the file gmshparser-0.3.1.tar.gz.

File metadata

  • Download URL: gmshparser-0.3.1.tar.gz
  • Upload date:
  • Size: 17.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.3 CPython/3.10.14 Linux/4.18.0-477.21.1.el8_8.x86_64

File hashes

Hashes for gmshparser-0.3.1.tar.gz
Algorithm Hash digest
SHA256 aaf84378c1867330dc3a0eae844b0189843b5a4563525d7a4a1d174c8d43510b
MD5 03d52b371c5adb1fc7e27b1f7c8e9857
BLAKE2b-256 cca1562040f55f86be76e47685d2b8a9f15bce0b0f14bffeff6c5be6a1a07035

See more details on using hashes here.

File details

Details for the file gmshparser-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: gmshparser-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 22.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.3 CPython/3.10.14 Linux/4.18.0-477.21.1.el8_8.x86_64

File hashes

Hashes for gmshparser-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 eda2e531e43757ab32177e60e6f3363a70531f8c695e012f9b13cbf72482a26a
MD5 5d0e81529f57ad4fb65c9309bd8ea4e5
BLAKE2b-256 f3ddae800d81e69491aff44c1d0cac941077ec28e0b38e2ac667bb6bd4fd14b9

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page